summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2012-02-16 14:23:04 +0200
committerJohan Hedberg <johan.hedberg@intel.com>2012-02-16 14:25:34 +0200
commit46479e698530b8197d601a23317b7c7654195338 (patch)
tree710b2758ecd7d8a6ada37724c5d4c8027d5f358f /drivers
parent7b99b659d90c5d421cb1867295c78a4c0c030734 (diff)
parentca994a36f585432458ead9133fcfe05440edbb7b (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next.git
Conflicts: include/net/bluetooth/l2cap.h net/bluetooth/hci_conn.c net/bluetooth/l2cap_core.c
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Makefile2
-rw-r--r--drivers/accessibility/braille/braille_console.c2
-rw-r--r--drivers/acpi/Makefile3
-rw-r--r--drivers/acpi/acpica/Makefile158
-rw-r--r--drivers/acpi/acpica/accommon.h2
-rw-r--r--drivers/acpi/acpica/acconfig.h9
-rw-r--r--drivers/acpi/acpica/acdebug.h2
-rw-r--r--drivers/acpi/acpica/acdispat.h2
-rw-r--r--drivers/acpi/acpica/acevents.h3
-rw-r--r--drivers/acpi/acpica/acglobal.h19
-rw-r--r--drivers/acpi/acpica/achware.h2
-rw-r--r--drivers/acpi/acpica/acinterp.h4
-rw-r--r--drivers/acpi/acpica/aclocal.h26
-rw-r--r--drivers/acpi/acpica/acmacros.h2
-rw-r--r--drivers/acpi/acpica/acnamesp.h2
-rw-r--r--drivers/acpi/acpica/acobject.h8
-rw-r--r--drivers/acpi/acpica/acopcode.h6
-rw-r--r--drivers/acpi/acpica/acparser.h2
-rw-r--r--drivers/acpi/acpica/acpredef.h41
-rw-r--r--drivers/acpi/acpica/acresrc.h115
-rw-r--r--drivers/acpi/acpica/acstruct.h2
-rw-r--r--drivers/acpi/acpica/actables.h2
-rw-r--r--drivers/acpi/acpica/acutils.h21
-rw-r--r--drivers/acpi/acpica/amlcode.h29
-rw-r--r--drivers/acpi/acpica/amlresrc.h138
-rw-r--r--drivers/acpi/acpica/dsargs.c18
-rw-r--r--drivers/acpi/acpica/dscontrol.c2
-rw-r--r--drivers/acpi/acpica/dsfield.c83
-rw-r--r--drivers/acpi/acpica/dsinit.c2
-rw-r--r--drivers/acpi/acpica/dsmethod.c2
-rw-r--r--drivers/acpi/acpica/dsmthdat.c2
-rw-r--r--drivers/acpi/acpica/dsobject.c2
-rw-r--r--drivers/acpi/acpica/dsopcode.c2
-rw-r--r--drivers/acpi/acpica/dsutils.c2
-rw-r--r--drivers/acpi/acpica/dswexec.c2
-rw-r--r--drivers/acpi/acpica/dswload.c2
-rw-r--r--drivers/acpi/acpica/dswload2.c2
-rw-r--r--drivers/acpi/acpica/dswscope.c2
-rw-r--r--drivers/acpi/acpica/dswstate.c2
-rw-r--r--drivers/acpi/acpica/evevent.c14
-rw-r--r--drivers/acpi/acpica/evglock.c8
-rw-r--r--drivers/acpi/acpica/evgpe.c2
-rw-r--r--drivers/acpi/acpica/evgpeblk.c2
-rw-r--r--drivers/acpi/acpica/evgpeinit.c2
-rw-r--r--drivers/acpi/acpica/evgpeutil.c2
-rw-r--r--drivers/acpi/acpica/evmisc.c2
-rw-r--r--drivers/acpi/acpica/evregion.c31
-rw-r--r--drivers/acpi/acpica/evrgnini.c2
-rw-r--r--drivers/acpi/acpica/evsci.c2
-rw-r--r--drivers/acpi/acpica/evxface.c2
-rw-r--r--drivers/acpi/acpica/evxfevnt.c2
-rw-r--r--drivers/acpi/acpica/evxfgpe.c2
-rw-r--r--drivers/acpi/acpica/evxfregn.c2
-rw-r--r--drivers/acpi/acpica/exconfig.c8
-rw-r--r--drivers/acpi/acpica/exconvrt.c2
-rw-r--r--drivers/acpi/acpica/excreate.c31
-rw-r--r--drivers/acpi/acpica/exdebug.c2
-rw-r--r--drivers/acpi/acpica/exdump.c9
-rw-r--r--drivers/acpi/acpica/exfield.c30
-rw-r--r--drivers/acpi/acpica/exfldio.c38
-rw-r--r--drivers/acpi/acpica/exmisc.c2
-rw-r--r--drivers/acpi/acpica/exmutex.c2
-rw-r--r--drivers/acpi/acpica/exnames.c2
-rw-r--r--drivers/acpi/acpica/exoparg1.c2
-rw-r--r--drivers/acpi/acpica/exoparg2.c2
-rw-r--r--drivers/acpi/acpica/exoparg3.c2
-rw-r--r--drivers/acpi/acpica/exoparg6.c2
-rw-r--r--drivers/acpi/acpica/exprep.c27
-rw-r--r--drivers/acpi/acpica/exregion.c2
-rw-r--r--drivers/acpi/acpica/exresnte.c2
-rw-r--r--drivers/acpi/acpica/exresolv.c2
-rw-r--r--drivers/acpi/acpica/exresop.c2
-rw-r--r--drivers/acpi/acpica/exstore.c2
-rw-r--r--drivers/acpi/acpica/exstoren.c2
-rw-r--r--drivers/acpi/acpica/exstorob.c2
-rw-r--r--drivers/acpi/acpica/exsystem.c2
-rw-r--r--drivers/acpi/acpica/exutils.c27
-rw-r--r--drivers/acpi/acpica/hwacpi.c2
-rw-r--r--drivers/acpi/acpica/hwgpe.c2
-rw-r--r--drivers/acpi/acpica/hwpci.c2
-rw-r--r--drivers/acpi/acpica/hwregs.c2
-rw-r--r--drivers/acpi/acpica/hwsleep.c2
-rw-r--r--drivers/acpi/acpica/hwtimer.c2
-rw-r--r--drivers/acpi/acpica/hwvalid.c4
-rw-r--r--drivers/acpi/acpica/hwxface.c2
-rw-r--r--drivers/acpi/acpica/nsaccess.c2
-rw-r--r--drivers/acpi/acpica/nsalloc.c2
-rw-r--r--drivers/acpi/acpica/nsdump.c2
-rw-r--r--drivers/acpi/acpica/nsdumpdv.c2
-rw-r--r--drivers/acpi/acpica/nseval.c2
-rw-r--r--drivers/acpi/acpica/nsinit.c2
-rw-r--r--drivers/acpi/acpica/nsload.c2
-rw-r--r--drivers/acpi/acpica/nsnames.c2
-rw-r--r--drivers/acpi/acpica/nsobject.c2
-rw-r--r--drivers/acpi/acpica/nsparse.c2
-rw-r--r--drivers/acpi/acpica/nspredef.c31
-rw-r--r--drivers/acpi/acpica/nsrepair.c3
-rw-r--r--drivers/acpi/acpica/nsrepair2.c7
-rw-r--r--drivers/acpi/acpica/nssearch.c2
-rw-r--r--drivers/acpi/acpica/nsutils.c2
-rw-r--r--drivers/acpi/acpica/nswalk.c2
-rw-r--r--drivers/acpi/acpica/nsxfeval.c2
-rw-r--r--drivers/acpi/acpica/nsxfname.c2
-rw-r--r--drivers/acpi/acpica/nsxfobj.c2
-rw-r--r--drivers/acpi/acpica/psargs.c143
-rw-r--r--drivers/acpi/acpica/psloop.c2
-rw-r--r--drivers/acpi/acpica/psopcode.c15
-rw-r--r--drivers/acpi/acpica/psparse.c2
-rw-r--r--drivers/acpi/acpica/psscope.c2
-rw-r--r--drivers/acpi/acpica/pstree.c8
-rw-r--r--drivers/acpi/acpica/psutils.c2
-rw-r--r--drivers/acpi/acpica/pswalk.c2
-rw-r--r--drivers/acpi/acpica/psxface.c2
-rw-r--r--drivers/acpi/acpica/rsaddr.c2
-rw-r--r--drivers/acpi/acpica/rscalc.c89
-rw-r--r--drivers/acpi/acpica/rscreate.c69
-rw-r--r--drivers/acpi/acpica/rsdump.c196
-rw-r--r--drivers/acpi/acpica/rsinfo.c58
-rw-r--r--drivers/acpi/acpica/rsio.c2
-rw-r--r--drivers/acpi/acpica/rsirq.c33
-rw-r--r--drivers/acpi/acpica/rslist.c77
-rw-r--r--drivers/acpi/acpica/rsmemory.c2
-rw-r--r--drivers/acpi/acpica/rsmisc.c269
-rw-r--r--drivers/acpi/acpica/rsserial.c441
-rw-r--r--drivers/acpi/acpica/rsutils.c56
-rw-r--r--drivers/acpi/acpica/rsxface.c52
-rw-r--r--drivers/acpi/acpica/tbfadt.c41
-rw-r--r--drivers/acpi/acpica/tbfind.c2
-rw-r--r--drivers/acpi/acpica/tbinstal.c2
-rw-r--r--drivers/acpi/acpica/tbutils.c9
-rw-r--r--drivers/acpi/acpica/tbxface.c2
-rw-r--r--drivers/acpi/acpica/tbxfroot.c2
-rw-r--r--drivers/acpi/acpica/utaddress.c294
-rw-r--r--drivers/acpi/acpica/utalloc.c2
-rw-r--r--drivers/acpi/acpica/utcopy.c2
-rw-r--r--drivers/acpi/acpica/utdebug.c2
-rw-r--r--drivers/acpi/acpica/utdecode.c6
-rw-r--r--drivers/acpi/acpica/utdelete.c15
-rw-r--r--drivers/acpi/acpica/uteval.c2
-rw-r--r--drivers/acpi/acpica/utglobal.c8
-rw-r--r--drivers/acpi/acpica/utids.c2
-rw-r--r--drivers/acpi/acpica/utinit.c3
-rw-r--r--drivers/acpi/acpica/utlock.c2
-rw-r--r--drivers/acpi/acpica/utmath.c2
-rw-r--r--drivers/acpi/acpica/utmisc.c2
-rw-r--r--drivers/acpi/acpica/utmutex.c11
-rw-r--r--drivers/acpi/acpica/utobject.c2
-rw-r--r--drivers/acpi/acpica/utosi.c2
-rw-r--r--drivers/acpi/acpica/utresrc.c278
-rw-r--r--drivers/acpi/acpica/utstate.c2
-rw-r--r--drivers/acpi/acpica/utxface.c40
-rw-r--r--drivers/acpi/acpica/utxferror.c2
-rw-r--r--drivers/acpi/acpica/utxfmutex.c187
-rw-r--r--drivers/acpi/apei/apei-base.c150
-rw-r--r--drivers/acpi/apei/apei-internal.h6
-rw-r--r--drivers/acpi/apei/einj.c290
-rw-r--r--drivers/acpi/apei/erst.c5
-rw-r--r--drivers/acpi/apei/ghes.c104
-rw-r--r--drivers/acpi/apei/hest.c7
-rw-r--r--drivers/acpi/atomicio.c77
-rw-r--r--drivers/acpi/dock.c2
-rw-r--r--drivers/acpi/numa.c6
-rw-r--r--drivers/acpi/nvs.c53
-rw-r--r--drivers/acpi/osl.c242
-rw-r--r--drivers/acpi/pci_slot.c2
-rw-r--r--drivers/acpi/processor_core.c26
-rw-r--r--drivers/acpi/processor_driver.c20
-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/Kconfig2
-rw-r--r--drivers/base/bus.c9
-rw-r--r--drivers/base/firmware_class.c3
-rw-r--r--drivers/base/power/domain.c15
-rw-r--r--drivers/base/power/domain_governor.c24
-rw-r--r--drivers/bcma/main.c4
-rw-r--r--drivers/bcma/scan.c19
-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.c1739
-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.c4
-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/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/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/random.c8
-rw-r--r--drivers/char/tpm/tpm.c9
-rw-r--r--drivers/char/tpm/tpm.h3
-rw-r--r--drivers/char/tpm/tpm_tis.c6
-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/gpio/Kconfig2
-rw-r--r--drivers/gpio/Makefile2
-rw-r--r--drivers/gpio/devres.c90
-rw-r--r--drivers/gpio/gpio-ml-ioh.c8
-rw-r--r--drivers/gpio/gpio-pch.c4
-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/gpio/gpio-tps65910.c2
-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/gtt.c5
-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/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/Kconfig18
-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.c21
-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-omap.c110
-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-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/idle/intel_idle.c96
-rw-r--r--drivers/infiniband/Kconfig1
-rw-r--r--drivers/infiniband/Makefile1
-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/infiniband/ulp/srpt/Kconfig12
-rw-r--r--drivers/infiniband/ulp/srpt/Makefile2
-rw-r--r--drivers/infiniband/ulp/srpt/ib_dm_mad.h139
-rw-r--r--drivers/infiniband/ulp/srpt/ib_srpt.c4073
-rw-r--r--drivers/infiniband/ulp/srpt/ib_srpt.h444
-rw-r--r--drivers/input/joystick/xpad.c6
-rw-r--r--drivers/input/misc/ab8500-ponkey.c2
-rw-r--r--drivers/input/misc/wistron_btns.c2
-rw-r--r--drivers/input/mouse/psmouse-base.c2
-rw-r--r--drivers/input/mouse/synaptics_i2c.c6
-rw-r--r--drivers/input/serio/hp_sdc.c2
-rw-r--r--drivers/input/touchscreen/eeti_ts.c4
-rw-r--r--drivers/input/touchscreen/htcpen.c4
-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/sc/init.c2
-rw-r--r--drivers/leds/Kconfig14
-rw-r--r--drivers/leds/Makefile2
-rw-r--r--drivers/leds/leds-clevo-mail.c2
-rw-r--r--drivers/leds/leds-max8997.c372
-rw-r--r--drivers/leds/leds-ot200.c171
-rw-r--r--drivers/leds/leds-ss4200.c2
-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.c1
-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.c143
-rw-r--r--drivers/media/common/tuners/xc4000.c191
-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.c922
-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.c403
-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.h2
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700_core.c1
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700_devices.c867
-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.c38
-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.c53
-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.c905
-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-fileops.c41
-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.c79
-rw-r--r--drivers/media/video/cx23885/cx23885-core.c24
-rw-r--r--drivers/media/video/cx23885/cx23885-dvb.c113
-rw-r--r--drivers/media/video/cx23885/cx23885-i2c.c2
-rw-r--r--drivers/media/video/cx23885/cx23885-video.c176
-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.c118
-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.c5
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.h3
-rw-r--r--drivers/media/video/ivtv/ivtv-fileops.c118
-rw-r--r--drivers/media/video/ivtv/ivtv-i2c.h2
-rw-r--r--drivers/media/video/ivtv/ivtv-ioctl.c22
-rw-r--r--drivers/media/video/ivtv/ivtv-irq.c4
-rw-r--r--drivers/media/video/ivtv/ivtv-streams.c2
-rw-r--r--drivers/media/video/ivtv/ivtv-yuv.c22
-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.c233
-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.c935
-rw-r--r--drivers/media/video/pwc/pwc-dec1.c16
-rw-r--r--drivers/media/video/pwc/pwc-dec1.h6
-rw-r--r--drivers/media/video/pwc/pwc-dec23.c307
-rw-r--r--drivers/media/video/pwc/pwc-dec23.h14
-rw-r--r--drivers/media/video/pwc/pwc-if.c460
-rw-r--r--drivers/media/video/pwc/pwc-kiara.h2
-rw-r--r--drivers/media/video/pwc/pwc-misc.c88
-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.c330
-rw-r--r--drivers/media/video/pwc/pwc.h78
-rw-r--r--drivers/media/video/pxa_camera.c17
-rw-r--r--drivers/media/video/s5p-fimc/fimc-capture.c18
-rw-r--r--drivers/media/video/s5p-fimc/fimc-core.c140
-rw-r--r--drivers/media/video/s5p-fimc/fimc-core.h30
-rw-r--r--drivers/media/video/s5p-fimc/fimc-mdevice.c1
-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.c811
-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.c1482
-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.c25
-rw-r--r--drivers/media/video/s5p-mfc/s5p_mfc_dec.c2
-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/saa7164/saa7164-cards.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/tlg2300/pd-main.c4
-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.c59
-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.c128
-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/zoran_driver.c1
-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/Kconfig35
-rw-r--r--drivers/mfd/Makefile3
-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-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/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/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/vtbl.c6
-rw-r--r--drivers/net/bonding/bond_alb.c27
-rw-r--r--drivers/net/dsa/mv88e6060.c1
-rw-r--r--drivers/net/dsa/mv88e6123_61_65.c22
-rw-r--r--drivers/net/dsa/mv88e6131.c1
-rw-r--r--drivers/net/dsa/mv88e6xxx.c1
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c2
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c111
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c11
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c44
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h11
-rw-r--r--drivers/net/ethernet/broadcom/tg3.c9
-rw-r--r--drivers/net/ethernet/cisco/enic/enic.h2
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_main.c38
-rw-r--r--drivers/net/ethernet/emulex/benet/be_main.c3
-rw-r--r--drivers/net/ethernet/faraday/ftgmac100.c1
-rw-r--r--drivers/net/ethernet/faraday/ftmac100.c1
-rw-r--r--drivers/net/ethernet/intel/igb/Makefile2
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_82575.c2
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_82575.h2
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_defines.h2
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_hw.h2
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_mac.c4
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_mac.h2
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_mbx.c2
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_mbx.h2
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_nvm.c2
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_nvm.h2
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_phy.c2
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_phy.h2
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_regs.h2
-rw-r--r--drivers/net/ethernet/intel/igb/igb.h2
-rw-r--r--drivers/net/ethernet/intel/igb/igb_ethtool.c2
-rw-r--r--drivers/net/ethernet/intel/igb/igb_main.c10
-rw-r--r--drivers/net/ethernet/intel/igbvf/ethtool.c3
-rw-r--r--drivers/net/ethernet/intel/igbvf/netdev.c5
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_type.h32
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/ethtool.c5
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/ixgbevf.h8
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c41
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/mbx.c3
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/vf.c7
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/vf.h2
-rw-r--r--drivers/net/ethernet/marvell/mv643xx_eth.c14
-rw-r--r--drivers/net/ethernet/marvell/skge.c109
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/cmd.c9
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/cq.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_ethtool.c159
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_main.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_netdev.c38
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_rx.c8
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/eq.c21
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/fw.c7
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/fw.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/main.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4.h8
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4_en.h3
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mr.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/pd.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/port.c23
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/profile.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/qp.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/resource_tracker.c39
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/srq.c2
-rw-r--r--drivers/net/ethernet/micrel/ks8842.c4
-rw-r--r--drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c17
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c6
-rw-r--r--drivers/net/hyperv/netvsc_drv.c5
-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/macvlan.c1
-rw-r--r--drivers/net/phy/mdio_bus.c5
-rw-r--r--drivers/net/team/team.c136
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c7
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c9
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tx.c14
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-pcie.c1
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.c8
-rw-r--r--drivers/net/wireless/mwifiex/init.c3
-rw-r--r--drivers/net/wireless/mwifiex/main.c12
-rw-r--r--drivers/net/wireless/mwifiex/sta_ioctl.c8
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c8
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c8
-rw-r--r--drivers/net/xen-netfront.c2
-rw-r--r--drivers/of/address.c16
-rw-r--r--drivers/of/irq.c11
-rw-r--r--drivers/parport/parport_ip32.c2
-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/pci-sysfs.c2
-rw-r--r--drivers/pci/pci.c6
-rw-r--r--drivers/pci/pcie/aer/aer_inject.c2
-rw-r--r--drivers/pci/pcie/aer/aerdrv_core.c4
-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/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/power/ds2760_battery.c2
-rw-r--r--drivers/regulator/ab8500.c2
-rw-r--r--drivers/regulator/core.c2
-rw-r--r--drivers/rtc/rtc-ab8500.c2
-rw-r--r--drivers/rtc/rtc-max8925.c26
-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/scsi/Kconfig5
-rw-r--r--drivers/scsi/aha1542.c2
-rw-r--r--drivers/scsi/bfa/bfa_defs_svc.h7
-rw-r--r--drivers/scsi/bfa/bfa_fc.h155
-rw-r--r--drivers/scsi/bfa/bfa_fcpim.c416
-rw-r--r--drivers/scsi/bfa/bfa_fcpim.h7
-rw-r--r--drivers/scsi/bfa/bfa_svc.h5
-rw-r--r--drivers/scsi/bfa/bfad.c2
-rw-r--r--drivers/scsi/bfa/bfad_attr.c2
-rw-r--r--drivers/scsi/bfa/bfad_bsg.c27
-rw-r--r--drivers/scsi/bfa/bfad_drv.h2
-rw-r--r--drivers/scsi/bfa/bfad_im.c56
-rw-r--r--drivers/scsi/bfa/bfad_im.h27
-rw-r--r--drivers/scsi/cxgbi/libcxgbi.c5
-rw-r--r--drivers/scsi/dc395x.c2
-rw-r--r--drivers/scsi/device_handler/scsi_dh_alua.c5
-rw-r--r--drivers/scsi/device_handler/scsi_dh_rdac.c2
-rw-r--r--drivers/scsi/fcoe/fcoe.c46
-rw-r--r--drivers/scsi/fcoe/fcoe.h4
-rw-r--r--drivers/scsi/hpsa.c2
-rw-r--r--drivers/scsi/isci/firmware/Makefile19
-rw-r--r--drivers/scsi/isci/firmware/README36
-rw-r--r--drivers/scsi/isci/firmware/create_fw.c99
-rw-r--r--drivers/scsi/isci/firmware/create_fw.h77
-rw-r--r--drivers/scsi/isci/host.c340
-rw-r--r--drivers/scsi/isci/host.h27
-rw-r--r--drivers/scsi/isci/init.c25
-rw-r--r--drivers/scsi/isci/isci.h1
-rw-r--r--drivers/scsi/isci/phy.c172
-rw-r--r--drivers/scsi/isci/port.c104
-rw-r--r--drivers/scsi/isci/port.h10
-rw-r--r--drivers/scsi/isci/port_config.c35
-rw-r--r--drivers/scsi/isci/probe_roms.c2
-rw-r--r--drivers/scsi/isci/probe_roms.h89
-rw-r--r--drivers/scsi/isci/remote_device.c10
-rw-r--r--drivers/scsi/isci/task.c2
-rw-r--r--drivers/scsi/isci/task.h7
-rw-r--r--drivers/scsi/libfc/fc_disc.c6
-rw-r--r--drivers/scsi/libfc/fc_elsct.c1
-rw-r--r--drivers/scsi/libfc/fc_exch.c2
-rw-r--r--drivers/scsi/libfc/fc_fcp.c4
-rw-r--r--drivers/scsi/libfc/fc_lport.c5
-rw-r--r--drivers/scsi/libfc/fc_rport.c10
-rw-r--r--drivers/scsi/megaraid.c13
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.h8
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_base.c145
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fp.c4
-rw-r--r--drivers/scsi/nsp32.c4
-rw-r--r--drivers/scsi/pcmcia/nsp_cs.c2
-rw-r--r--drivers/scsi/qla4xxx/ql4_def.h3
-rw-r--r--drivers/scsi/qla4xxx/ql4_init.c3
-rw-r--r--drivers/scsi/qla4xxx/ql4_mbx.c7
-rw-r--r--drivers/scsi/qla4xxx/ql4_nx.c5
-rw-r--r--drivers/scsi/qla4xxx/ql4_nx.h22
-rw-r--r--drivers/scsi/qla4xxx/ql4_os.c511
-rw-r--r--drivers/scsi/qla4xxx/ql4_version.h2
-rw-r--r--drivers/scsi/scsi_lib.c7
-rw-r--r--drivers/scsi/scsi_netlink.c2
-rw-r--r--drivers/scsi/scsi_scan.c2
-rw-r--r--drivers/scsi/scsi_transport_fc.c3
-rw-r--r--drivers/scsi/sd.c13
-rw-r--r--drivers/scsi/sg.c25
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.c4
-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/ssb/driver_pcicore.c2
-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/target/iscsi/iscsi_target.c19
-rw-r--r--drivers/target/iscsi/iscsi_target_auth.c36
-rw-r--r--drivers/target/iscsi/iscsi_target_configfs.c11
-rw-r--r--drivers/target/iscsi/iscsi_target_device.c3
-rw-r--r--drivers/target/iscsi/iscsi_target_erl0.c2
-rw-r--r--drivers/target/iscsi/iscsi_target_erl1.c2
-rw-r--r--drivers/target/iscsi/iscsi_target_erl2.c2
-rw-r--r--drivers/target/iscsi/iscsi_target_login.c23
-rw-r--r--drivers/target/iscsi/iscsi_target_nego.c4
-rw-r--r--drivers/target/iscsi/iscsi_target_nodeattrib.c3
-rw-r--r--drivers/target/iscsi/iscsi_target_stat.c17
-rw-r--r--drivers/target/iscsi/iscsi_target_tmr.c2
-rw-r--r--drivers/target/iscsi/iscsi_target_tpg.c6
-rw-r--r--drivers/target/iscsi/iscsi_target_util.c8
-rw-r--r--drivers/target/loopback/tcm_loop.c33
-rw-r--r--drivers/target/loopback/tcm_loop.h11
-rw-r--r--drivers/target/target_core_alua.c7
-rw-r--r--drivers/target/target_core_cdb.c39
-rw-r--r--drivers/target/target_core_cdb.h14
-rw-r--r--drivers/target/target_core_configfs.c34
-rw-r--r--drivers/target/target_core_device.c15
-rw-r--r--drivers/target/target_core_fabric_configfs.c8
-rw-r--r--drivers/target/target_core_fabric_lib.c13
-rw-r--r--drivers/target/target_core_file.c15
-rw-r--r--drivers/target/target_core_hba.c7
-rw-r--r--drivers/target/target_core_hba.h7
-rw-r--r--drivers/target/target_core_iblock.c7
-rw-r--r--drivers/target/target_core_internal.h123
-rw-r--r--drivers/target/target_core_pr.c24
-rw-r--r--drivers/target/target_core_pr.h2
-rw-r--r--drivers/target/target_core_pscsi.c20
-rw-r--r--drivers/target/target_core_rd.c6
-rw-r--r--drivers/target/target_core_stat.c9
-rw-r--r--drivers/target/target_core_stat.h8
-rw-r--r--drivers/target/target_core_tmr.c36
-rw-r--r--drivers/target/target_core_tpg.c9
-rw-r--r--drivers/target/target_core_transport.c343
-rw-r--r--drivers/target/target_core_ua.c6
-rw-r--r--drivers/target/tcm_fc/tfc_cmd.c57
-rw-r--r--drivers/target/tcm_fc/tfc_conf.c6
-rw-r--r--drivers/target/tcm_fc/tfc_io.c5
-rw-r--r--drivers/target/tcm_fc/tfc_sess.c5
-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.c4
-rw-r--r--drivers/tty/synclink.c2
-rw-r--r--drivers/tty/synclinkmp.c2
-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/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/adp8860_bl.c2
-rw-r--r--drivers/video/backlight/adp8870_bl.c2
-rw-r--r--drivers/video/backlight/l4f00242t03.c2
-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/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/watchdog/f71808e_wdt.c2
-rw-r--r--drivers/watchdog/mpc8xxx_wdt.c2
-rw-r--r--drivers/xen/biomerge.c2
-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
1528 files changed, 63698 insertions, 49628 deletions
diff --git a/drivers/Makefile b/drivers/Makefile
index 1b3142127bf5..c07be024b962 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 cb423f5aef24..c339a0880e6e 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/Makefile b/drivers/acpi/Makefile
index ecb26b4f29a0..c07f44f05f9d 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -20,11 +20,12 @@ obj-y += acpi.o \
# All the builtin files are in the "acpi." module_param namespace.
acpi-y += osl.o utils.o reboot.o
acpi-y += atomicio.o
+acpi-y += nvs.o
# sleep related files
acpi-y += wakeup.o
acpi-y += sleep.o
-acpi-$(CONFIG_ACPI_SLEEP) += proc.o nvs.o
+acpi-$(CONFIG_ACPI_SLEEP) += proc.o
#
diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile
index 301bd2d388ad..0ca208b6dcf0 100644
--- a/drivers/acpi/acpica/Makefile
+++ b/drivers/acpi/acpica/Makefile
@@ -8,41 +8,151 @@ ccflags-$(CONFIG_ACPI_DEBUG) += -DACPI_DEBUG_OUTPUT
# use acpi.o to put all files here into acpi.o modparam namespace
obj-y += acpi.o
-acpi-y := dsfield.o dsmthdat.o dsopcode.o dswexec.o dswscope.o \
- dsmethod.o dsobject.o dsutils.o dswload.o dswstate.o \
- dsinit.o dsargs.o dscontrol.o dswload2.o
+acpi-y := \
+ dsargs.o \
+ dscontrol.o \
+ dsfield.o \
+ dsinit.o \
+ dsmethod.o \
+ dsmthdat.o \
+ dsobject.o \
+ dsopcode.o \
+ dsutils.o \
+ dswexec.o \
+ dswload.o \
+ dswload2.o \
+ dswscope.o \
+ dswstate.o
-acpi-y += evevent.o evregion.o evsci.o evxfevnt.o \
- evmisc.o evrgnini.o evxface.o evxfregn.o \
- evgpe.o evgpeblk.o evgpeinit.o evgpeutil.o evxfgpe.o evglock.o
+acpi-y += \
+ evevent.o \
+ evgpe.o \
+ evgpeblk.o \
+ evgpeinit.o \
+ evgpeutil.o \
+ evglock.o \
+ evmisc.o \
+ evregion.o \
+ evrgnini.o \
+ evsci.o \
+ evxface.o \
+ evxfevnt.o \
+ evxfgpe.o \
+ evxfregn.o
-acpi-y += exconfig.o exfield.o exnames.o exoparg6.o exresolv.o exstorob.o\
- exconvrt.o exfldio.o exoparg1.o exprep.o exresop.o exsystem.o\
- excreate.o exmisc.o exoparg2.o exregion.o exstore.o exutils.o \
- exdump.o exmutex.o exoparg3.o exresnte.o exstoren.o exdebug.o
+acpi-y += \
+ exconfig.o \
+ exconvrt.o \
+ excreate.o \
+ exdebug.o \
+ exdump.o \
+ exfield.o \
+ exfldio.o \
+ exmutex.o \
+ exnames.o \
+ exoparg1.o \
+ exoparg2.o \
+ exoparg3.o \
+ exoparg6.o \
+ exprep.o \
+ exmisc.o \
+ exregion.o \
+ exresnte.o \
+ exresolv.o \
+ exresop.o \
+ exstore.o \
+ exstoren.o \
+ exstorob.o \
+ exsystem.o \
+ exutils.o
-acpi-y += hwacpi.o hwgpe.o hwregs.o hwsleep.o hwxface.o hwvalid.o hwpci.o
+acpi-y += \
+ hwacpi.o \
+ hwgpe.o \
+ hwpci.o \
+ hwregs.o \
+ hwsleep.o \
+ hwvalid.o \
+ hwxface.o
acpi-$(ACPI_FUTURE_USAGE) += hwtimer.o
-acpi-y += nsaccess.o nsload.o nssearch.o nsxfeval.o \
- nsalloc.o nseval.o nsnames.o nsutils.o nsxfname.o \
- nsdump.o nsinit.o nsobject.o nswalk.o nsxfobj.o \
- nsparse.o nspredef.o nsrepair.o nsrepair2.o
+acpi-y += \
+ nsaccess.o \
+ nsalloc.o \
+ nsdump.o \
+ nseval.o \
+ nsinit.o \
+ nsload.o \
+ nsnames.o \
+ nsobject.o \
+ nsparse.o \
+ nspredef.o \
+ nsrepair.o \
+ nsrepair2.o \
+ nssearch.o \
+ nsutils.o \
+ nswalk.o \
+ nsxfeval.o \
+ nsxfname.o \
+ nsxfobj.o
acpi-$(ACPI_FUTURE_USAGE) += nsdumpdv.o
-acpi-y += psargs.o psparse.o psloop.o pstree.o pswalk.o \
- psopcode.o psscope.o psutils.o psxface.o
+acpi-y += \
+ psargs.o \
+ psloop.o \
+ psopcode.o \
+ psparse.o \
+ psscope.o \
+ pstree.o \
+ psutils.o \
+ pswalk.o \
+ psxface.o
-acpi-y += rsaddr.o rscreate.o rsinfo.o rsio.o rslist.o rsmisc.o rsxface.o \
- rscalc.o rsirq.o rsmemory.o rsutils.o
+acpi-y += \
+ rsaddr.o \
+ rscalc.o \
+ rscreate.o \
+ rsinfo.o \
+ rsio.o \
+ rsirq.o \
+ rslist.o \
+ rsmemory.o \
+ rsmisc.o \
+ rsserial.o \
+ rsutils.o \
+ rsxface.o
acpi-$(ACPI_FUTURE_USAGE) += rsdump.o
-acpi-y += tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o tbxfroot.o
+acpi-y += \
+ tbfadt.o \
+ tbfind.o \
+ tbinstal.o \
+ tbutils.o \
+ tbxface.o \
+ tbxfroot.o
-acpi-y += utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \
- utcopy.o utdelete.o utglobal.o utmath.o utobject.o \
- utstate.o utmutex.o utobject.o utresrc.o utlock.o utids.o \
- utosi.o utxferror.o utdecode.o
+acpi-y += \
+ utaddress.o \
+ utalloc.o \
+ utcopy.o \
+ utdebug.o \
+ utdecode.o \
+ utdelete.o \
+ uteval.o \
+ utglobal.o \
+ utids.o \
+ utinit.o \
+ utlock.o \
+ utmath.o \
+ utmisc.o \
+ utmutex.o \
+ utobject.o \
+ utosi.o \
+ utresrc.o \
+ utstate.o \
+ utxface.o \
+ utxferror.o \
+ utxfmutex.o
diff --git a/drivers/acpi/acpica/accommon.h b/drivers/acpi/acpica/accommon.h
index e0ba17f0a7c8..a44bd424f9f4 100644
--- a/drivers/acpi/acpica/accommon.h
+++ b/drivers/acpi/acpica/accommon.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/acconfig.h b/drivers/acpi/acpica/acconfig.h
index f895a244ca7e..1f30af613e87 100644
--- a/drivers/acpi/acpica/acconfig.h
+++ b/drivers/acpi/acpica/acconfig.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -123,6 +123,10 @@
#define ACPI_MAX_SLEEP 2000 /* Two seconds */
+/* Address Range lists are per-space_id (Memory and I/O only) */
+
+#define ACPI_ADDRESS_RANGE_MAX 2
+
/******************************************************************************
*
* ACPI Specification constants (Do not change unless the specification changes)
@@ -202,9 +206,10 @@
#define ACPI_RSDP_CHECKSUM_LENGTH 20
#define ACPI_RSDP_XCHECKSUM_LENGTH 36
-/* SMBus and IPMI bidirectional buffer size */
+/* SMBus, GSBus and IPMI bidirectional buffer size */
#define ACPI_SMBUS_BUFFER_SIZE 34
+#define ACPI_GSBUS_BUFFER_SIZE 34
#define ACPI_IPMI_BUFFER_SIZE 66
/* _sx_d and _sx_w control methods */
diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h
index eb0b1f8dee6d..deaa81979561 100644
--- a/drivers/acpi/acpica/acdebug.h
+++ b/drivers/acpi/acpica/acdebug.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/acdispat.h b/drivers/acpi/acpica/acdispat.h
index 2d1b7ffa377a..5935ba6707e2 100644
--- a/drivers/acpi/acpica/acdispat.h
+++ b/drivers/acpi/acpica/acdispat.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h
index bea3b4899183..c53caa521a30 100644
--- a/drivers/acpi/acpica/acevents.h
+++ b/drivers/acpi/acpica/acevents.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -162,6 +162,7 @@ acpi_status acpi_ev_initialize_op_regions(void);
acpi_status
acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
+ union acpi_operand_object *field_obj,
u32 function,
u32 region_offset, u32 bit_width, u64 *value);
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h
index 76dc02f15574..2853f7673f3b 100644
--- a/drivers/acpi/acpica/acglobal.h
+++ b/drivers/acpi/acpica/acglobal.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -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
@@ -140,8 +140,19 @@ u32 acpi_gbl_trace_flags;
acpi_name acpi_gbl_trace_method_name;
u8 acpi_gbl_system_awake_and_running;
+/*
+ * ACPI 5.0 introduces the concept of a "reduced hardware platform", meaning
+ * that the ACPI hardware is no longer required. A flag in the FADT indicates
+ * a reduced HW machine, and that flag is duplicated here for convenience.
+ */
+u8 acpi_gbl_reduced_hardware;
+
#endif
+/* Do not disassemble buffers to resource descriptors */
+
+ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_no_resource_disassembly, FALSE);
+
/*****************************************************************************
*
* Debug support
@@ -207,7 +218,7 @@ ACPI_EXTERN struct acpi_rw_lock acpi_gbl_namespace_rw_lock;
/*****************************************************************************
*
- * Mutual exlusion within ACPICA subsystem
+ * Mutual exclusion within ACPICA subsystem
*
****************************************************************************/
@@ -295,6 +306,8 @@ ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present;
ACPI_EXTERN u8 acpi_gbl_events_initialized;
ACPI_EXTERN u8 acpi_gbl_osi_data;
ACPI_EXTERN struct acpi_interface_info *acpi_gbl_supported_interfaces;
+ACPI_EXTERN struct acpi_address_range
+ *acpi_gbl_address_range_list[ACPI_ADDRESS_RANGE_MAX];
#ifndef DEFINE_ACPI_GLOBALS
diff --git a/drivers/acpi/acpica/achware.h b/drivers/acpi/acpica/achware.h
index e7213beaafc7..677793e938f5 100644
--- a/drivers/acpi/acpica/achware.h
+++ b/drivers/acpi/acpica/achware.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/acinterp.h b/drivers/acpi/acpica/acinterp.h
index 3731e1c34b83..eb308635da72 100644
--- a/drivers/acpi/acpica/acinterp.h
+++ b/drivers/acpi/acpica/acinterp.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -468,6 +468,8 @@ void acpi_ex_eisa_id_to_string(char *dest, u64 compressed_id);
void acpi_ex_integer_to_string(char *dest, u64 value);
+u8 acpi_is_valid_space_id(u8 space_id);
+
/*
* exregion - default op_region handlers
*/
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h
index 5552125d8340..3f24068837d5 100644
--- a/drivers/acpi/acpica/aclocal.h
+++ b/drivers/acpi/acpica/aclocal.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -53,7 +53,7 @@ typedef u32 acpi_mutex_handle;
/* Total number of aml opcodes defined */
-#define AML_NUM_OPCODES 0x7F
+#define AML_NUM_OPCODES 0x81
/* Forward declarations */
@@ -249,12 +249,16 @@ struct acpi_create_field_info {
struct acpi_namespace_node *field_node;
struct acpi_namespace_node *register_node;
struct acpi_namespace_node *data_register_node;
+ struct acpi_namespace_node *connection_node;
+ u8 *resource_buffer;
u32 bank_value;
u32 field_bit_position;
u32 field_bit_length;
+ u16 resource_length;
u8 field_flags;
u8 attribute;
u8 field_type;
+ u8 access_length;
};
typedef
@@ -315,7 +319,8 @@ struct acpi_name_info {
/*
* Used for ACPI_PTYPE1_FIXED, ACPI_PTYPE1_VAR, ACPI_PTYPE2,
- * ACPI_PTYPE2_MIN, ACPI_PTYPE2_PKG_COUNT, ACPI_PTYPE2_COUNT
+ * ACPI_PTYPE2_MIN, ACPI_PTYPE2_PKG_COUNT, ACPI_PTYPE2_COUNT,
+ * ACPI_PTYPE2_FIX_VAR
*/
struct acpi_package_info {
u8 type;
@@ -625,6 +630,15 @@ union acpi_generic_state {
typedef acpi_status(*ACPI_EXECUTE_OP) (struct acpi_walk_state * walk_state);
+/* Address Range info block */
+
+struct acpi_address_range {
+ struct acpi_address_range *next;
+ struct acpi_namespace_node *region_node;
+ acpi_physical_address start_address;
+ acpi_physical_address end_address;
+};
+
/*****************************************************************************
*
* Parser typedefs and structs
@@ -951,7 +965,7 @@ struct acpi_port_info {
#define ACPI_RESOURCE_NAME_END_DEPENDENT 0x38
#define ACPI_RESOURCE_NAME_IO 0x40
#define ACPI_RESOURCE_NAME_FIXED_IO 0x48
-#define ACPI_RESOURCE_NAME_RESERVED_S1 0x50
+#define ACPI_RESOURCE_NAME_FIXED_DMA 0x50
#define ACPI_RESOURCE_NAME_RESERVED_S2 0x58
#define ACPI_RESOURCE_NAME_RESERVED_S3 0x60
#define ACPI_RESOURCE_NAME_RESERVED_S4 0x68
@@ -973,7 +987,9 @@ struct acpi_port_info {
#define ACPI_RESOURCE_NAME_EXTENDED_IRQ 0x89
#define ACPI_RESOURCE_NAME_ADDRESS64 0x8A
#define ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64 0x8B
-#define ACPI_RESOURCE_NAME_LARGE_MAX 0x8B
+#define ACPI_RESOURCE_NAME_GPIO 0x8C
+#define ACPI_RESOURCE_NAME_SERIAL_BUS 0x8E
+#define ACPI_RESOURCE_NAME_LARGE_MAX 0x8E
/*****************************************************************************
*
diff --git a/drivers/acpi/acpica/acmacros.h b/drivers/acpi/acpica/acmacros.h
index b7491ee1fba6..ef338a96f5b2 100644
--- a/drivers/acpi/acpica/acmacros.h
+++ b/drivers/acpi/acpica/acmacros.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h
index 79a598c67fe3..2c9e0f049523 100644
--- a/drivers/acpi/acpica/acnamesp.h
+++ b/drivers/acpi/acpica/acnamesp.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h
index 1055769f2f01..c065078ca83b 100644
--- a/drivers/acpi/acpica/acobject.h
+++ b/drivers/acpi/acpica/acobject.h
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -254,6 +254,7 @@ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO};
u32 base_byte_offset; /* Byte offset within containing object */\
u32 value; /* Value to store into the Bank or Index register */\
u8 start_field_bit_offset;/* Bit offset within first field datum (0-63) */\
+ u8 access_length; /* For serial regions/fields */
struct acpi_object_field_common { /* COMMON FIELD (for BUFFER, REGION, BANK, and INDEX fields) */
@@ -261,7 +262,9 @@ struct acpi_object_field_common { /* COMMON FIELD (for BUFFER, REGION, BANK, and
};
struct acpi_object_region_field {
- ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object *region_obj; /* Containing op_region object */
+ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO u16 resource_length;
+ union acpi_operand_object *region_obj; /* Containing op_region object */
+ u8 *resource_buffer; /* resource_template for serial regions/fields */
};
struct acpi_object_bank_field {
@@ -358,6 +361,7 @@ typedef enum {
*/
struct acpi_object_extra {
ACPI_OBJECT_COMMON_HEADER struct acpi_namespace_node *method_REG; /* _REG method for this region (if any) */
+ struct acpi_namespace_node *scope_node;
void *region_context; /* Region-specific data */
u8 *aml_start;
u32 aml_length;
diff --git a/drivers/acpi/acpica/acopcode.h b/drivers/acpi/acpica/acopcode.h
index bb2ccfad7376..9440d053fbb3 100644
--- a/drivers/acpi/acpica/acopcode.h
+++ b/drivers/acpi/acpica/acopcode.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -93,6 +93,7 @@
#define ARGP_CONCAT_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
#define ARGP_CONCAT_RES_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
#define ARGP_COND_REF_OF_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_SUPERNAME)
+#define ARGP_CONNECTFIELD_OP ARGP_LIST1 (ARGP_NAMESTRING)
#define ARGP_CONTINUE_OP ARG_NONE
#define ARGP_COPY_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_SIMPLENAME)
#define ARGP_CREATE_BIT_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME)
@@ -164,6 +165,7 @@
#define ARGP_RETURN_OP ARGP_LIST1 (ARGP_TERMARG)
#define ARGP_REVISION_OP ARG_NONE
#define ARGP_SCOPE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_TERMLIST)
+#define ARGP_SERIALFIELD_OP ARGP_LIST1 (ARGP_NAMESTRING)
#define ARGP_SHIFT_LEFT_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
#define ARGP_SHIFT_RIGHT_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
#define ARGP_SIGNAL_OP ARGP_LIST1 (ARGP_SUPERNAME)
@@ -223,6 +225,7 @@
#define ARGI_CONCAT_OP ARGI_LIST3 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA, ARGI_TARGETREF)
#define ARGI_CONCAT_RES_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_BUFFER, ARGI_TARGETREF)
#define ARGI_COND_REF_OF_OP ARGI_LIST2 (ARGI_OBJECT_REF, ARGI_TARGETREF)
+#define ARGI_CONNECTFIELD_OP ARGI_INVALID_OPCODE
#define ARGI_CONTINUE_OP ARGI_INVALID_OPCODE
#define ARGI_COPY_OP ARGI_LIST2 (ARGI_ANYTYPE, ARGI_SIMPLE_TARGET)
#define ARGI_CREATE_BIT_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE)
@@ -294,6 +297,7 @@
#define ARGI_RETURN_OP ARGI_INVALID_OPCODE
#define ARGI_REVISION_OP ARG_NONE
#define ARGI_SCOPE_OP ARGI_INVALID_OPCODE
+#define ARGI_SERIALFIELD_OP ARGI_INVALID_OPCODE
#define ARGI_SHIFT_LEFT_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
#define ARGI_SHIFT_RIGHT_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
#define ARGI_SIGNAL_OP ARGI_LIST1 (ARGI_EVENT)
diff --git a/drivers/acpi/acpica/acparser.h b/drivers/acpi/acpica/acparser.h
index 5ea1e06afa20..b725d780d34d 100644
--- a/drivers/acpi/acpica/acparser.h
+++ b/drivers/acpi/acpica/acparser.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/acpredef.h b/drivers/acpi/acpica/acpredef.h
index c445cca490ea..bbb34c9be4e8 100644
--- a/drivers/acpi/acpica/acpredef.h
+++ b/drivers/acpi/acpica/acpredef.h
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -94,6 +94,14 @@
* ACPI_PTYPE2_REV_FIXED: Revision at start, each subpackage is Fixed-length
* (Used for _ART, _FPS)
*
+ * ACPI_PTYPE2_FIX_VAR: Each subpackage consists of some fixed-length elements
+ * followed by an optional element
+ * object type
+ * count
+ * object type
+ * count = 0 (optional)
+ * (Used for _DLM)
+ *
*****************************************************************************/
enum acpi_return_package_types {
@@ -105,7 +113,8 @@ enum acpi_return_package_types {
ACPI_PTYPE2_PKG_COUNT = 6,
ACPI_PTYPE2_FIXED = 7,
ACPI_PTYPE2_MIN = 8,
- ACPI_PTYPE2_REV_FIXED = 9
+ ACPI_PTYPE2_REV_FIXED = 9,
+ ACPI_PTYPE2_FIX_VAR = 10
};
#ifdef ACPI_CREATE_PREDEFINED_TABLE
@@ -154,6 +163,7 @@ static const union acpi_predefined_info predefined_names[] =
{{"_AC8", 0, ACPI_RTYPE_INTEGER}},
{{"_AC9", 0, ACPI_RTYPE_INTEGER}},
{{"_ADR", 0, ACPI_RTYPE_INTEGER}},
+ {{"_AEI", 0, ACPI_RTYPE_BUFFER}},
{{"_AL0", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}},
@@ -229,6 +239,13 @@ static const union acpi_predefined_info predefined_names[] =
{{"_CID", 0, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_PACKAGE}}, /* Variable-length (Ints/Strs) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING, 0,0}, 0,0}},
+ {{"_CLS", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (3 Int) */
+ {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 3, 0}, 0, 0}},
+
+ {{"_CPC", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Ints/Bufs) */
+ {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER | ACPI_RTYPE_BUFFER, 0, 0}, 0,
+ 0}},
+
{{"_CRS", 0, ACPI_RTYPE_BUFFER}},
{{"_CRT", 0, ACPI_RTYPE_INTEGER}},
{{"_CSD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (1 Int(n), n-1 Int) */
@@ -237,12 +254,21 @@ static const union acpi_predefined_info predefined_names[] =
{{"_CST", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (1 Int(n), n Pkg (1 Buf/3 Int) */
{{{ACPI_PTYPE2_PKG_COUNT,ACPI_RTYPE_BUFFER, 1, ACPI_RTYPE_INTEGER}, 3,0}},
+ {{"_CWS", 1, ACPI_RTYPE_INTEGER}},
{{"_DCK", 1, ACPI_RTYPE_INTEGER}},
{{"_DCS", 0, ACPI_RTYPE_INTEGER}},
{{"_DDC", 1, ACPI_RTYPE_INTEGER | ACPI_RTYPE_BUFFER}},
{{"_DDN", 0, ACPI_RTYPE_STRING}},
+ {{"_DEP", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */
+ {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0}, 0, 0}},
+
{{"_DGS", 0, ACPI_RTYPE_INTEGER}},
{{"_DIS", 0, 0}},
+
+ {{"_DLM", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (1 Ref, 0/1 Optional Buf/Ref) */
+ {{{ACPI_PTYPE2_FIX_VAR, ACPI_RTYPE_REFERENCE, 1,
+ ACPI_RTYPE_REFERENCE | ACPI_RTYPE_BUFFER}, 0, 0}},
+
{{"_DMA", 0, ACPI_RTYPE_BUFFER}},
{{"_DOD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Ints) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0,0}, 0,0}},
@@ -262,6 +288,7 @@ static const union acpi_predefined_info predefined_names[] =
{{"_EJ3", 1, 0}},
{{"_EJ4", 1, 0}},
{{"_EJD", 0, ACPI_RTYPE_STRING}},
+ {{"_EVT", 1, 0}},
{{"_FDE", 0, ACPI_RTYPE_BUFFER}},
{{"_FDI", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (16 Int) */
{{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 16,0}, 0,0}},
@@ -281,14 +308,17 @@ static const union acpi_predefined_info predefined_names[] =
{{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 3, 0}, 0, 0}},
{{"_GAI", 0, ACPI_RTYPE_INTEGER}},
+ {{"_GCP", 0, ACPI_RTYPE_INTEGER}},
{{"_GHL", 0, ACPI_RTYPE_INTEGER}},
{{"_GLK", 0, ACPI_RTYPE_INTEGER}},
{{"_GPD", 0, ACPI_RTYPE_INTEGER}},
{{"_GPE", 0, ACPI_RTYPE_INTEGER}}, /* _GPE method, not _GPE scope */
+ {{"_GRT", 0, ACPI_RTYPE_BUFFER}},
{{"_GSB", 0, ACPI_RTYPE_INTEGER}},
{{"_GTF", 0, ACPI_RTYPE_BUFFER}},
{{"_GTM", 0, ACPI_RTYPE_BUFFER}},
{{"_GTS", 1, 0}},
+ {{"_GWS", 1, ACPI_RTYPE_INTEGER}},
{{"_HID", 0, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING}},
{{"_HOT", 0, ACPI_RTYPE_INTEGER}},
{{"_HPP", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (4 Int) */
@@ -303,6 +333,7 @@ static const union acpi_predefined_info predefined_names[] =
{{"_HPX", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (var Ints) */
{{{ACPI_PTYPE2_MIN, ACPI_RTYPE_INTEGER, 5,0}, 0,0}},
+ {{"_HRV", 0, ACPI_RTYPE_INTEGER}},
{{"_IFT", 0, ACPI_RTYPE_INTEGER}}, /* See IPMI spec */
{{"_INI", 0, 0}},
{{"_IRC", 0, 0}},
@@ -361,6 +392,9 @@ static const union acpi_predefined_info predefined_names[] =
{{"_PR3", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0}, 0, 0}},
+ {{"_PRE", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */
+ {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0}, 0, 0}},
+
{{"_PRL", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0}, 0, 0}},
@@ -391,6 +425,7 @@ static const union acpi_predefined_info predefined_names[] =
{{"_PSD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (5 Int) with count */
{{{ACPI_PTYPE2_COUNT, ACPI_RTYPE_INTEGER,0,0}, 0,0}},
+ {{"_PSE", 1, 0}},
{{"_PSL", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */
{{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}},
@@ -457,6 +492,7 @@ static const union acpi_predefined_info predefined_names[] =
{{"_SLI", 0, ACPI_RTYPE_BUFFER}},
{{"_SPD", 1, ACPI_RTYPE_INTEGER}},
{{"_SRS", 1, 0}},
+ {{"_SRT", 1, ACPI_RTYPE_INTEGER}},
{{"_SRV", 0, ACPI_RTYPE_INTEGER}}, /* See IPMI spec */
{{"_SST", 1, 0}},
{{"_STA", 0, ACPI_RTYPE_INTEGER}},
@@ -464,6 +500,7 @@ static const union acpi_predefined_info predefined_names[] =
{{"_STP", 2, ACPI_RTYPE_INTEGER}},
{{"_STR", 0, ACPI_RTYPE_BUFFER}},
{{"_STV", 2, ACPI_RTYPE_INTEGER}},
+ {{"_SUB", 0, ACPI_RTYPE_STRING}},
{{"_SUN", 0, ACPI_RTYPE_INTEGER}},
{{"_SWS", 0, ACPI_RTYPE_INTEGER}},
{{"_TC1", 0, ACPI_RTYPE_INTEGER}},
diff --git a/drivers/acpi/acpica/acresrc.h b/drivers/acpi/acpica/acresrc.h
index f08b55b7f3a0..0347d0993497 100644
--- a/drivers/acpi/acpica/acresrc.h
+++ b/drivers/acpi/acpica/acresrc.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -73,28 +73,40 @@ typedef const struct acpi_rsconvert_info {
/* Resource conversion opcodes */
-#define ACPI_RSC_INITGET 0
-#define ACPI_RSC_INITSET 1
-#define ACPI_RSC_FLAGINIT 2
-#define ACPI_RSC_1BITFLAG 3
-#define ACPI_RSC_2BITFLAG 4
-#define ACPI_RSC_COUNT 5
-#define ACPI_RSC_COUNT16 6
-#define ACPI_RSC_LENGTH 7
-#define ACPI_RSC_MOVE8 8
-#define ACPI_RSC_MOVE16 9
-#define ACPI_RSC_MOVE32 10
-#define ACPI_RSC_MOVE64 11
-#define ACPI_RSC_SET8 12
-#define ACPI_RSC_DATA8 13
-#define ACPI_RSC_ADDRESS 14
-#define ACPI_RSC_SOURCE 15
-#define ACPI_RSC_SOURCEX 16
-#define ACPI_RSC_BITMASK 17
-#define ACPI_RSC_BITMASK16 18
-#define ACPI_RSC_EXIT_NE 19
-#define ACPI_RSC_EXIT_LE 20
-#define ACPI_RSC_EXIT_EQ 21
+typedef enum {
+ ACPI_RSC_INITGET = 0,
+ ACPI_RSC_INITSET,
+ ACPI_RSC_FLAGINIT,
+ ACPI_RSC_1BITFLAG,
+ ACPI_RSC_2BITFLAG,
+ ACPI_RSC_3BITFLAG,
+ ACPI_RSC_ADDRESS,
+ ACPI_RSC_BITMASK,
+ ACPI_RSC_BITMASK16,
+ ACPI_RSC_COUNT,
+ ACPI_RSC_COUNT16,
+ ACPI_RSC_COUNT_GPIO_PIN,
+ ACPI_RSC_COUNT_GPIO_RES,
+ ACPI_RSC_COUNT_GPIO_VEN,
+ ACPI_RSC_COUNT_SERIAL_RES,
+ ACPI_RSC_COUNT_SERIAL_VEN,
+ ACPI_RSC_DATA8,
+ ACPI_RSC_EXIT_EQ,
+ ACPI_RSC_EXIT_LE,
+ ACPI_RSC_EXIT_NE,
+ ACPI_RSC_LENGTH,
+ ACPI_RSC_MOVE_GPIO_PIN,
+ ACPI_RSC_MOVE_GPIO_RES,
+ ACPI_RSC_MOVE_SERIAL_RES,
+ ACPI_RSC_MOVE_SERIAL_VEN,
+ ACPI_RSC_MOVE8,
+ ACPI_RSC_MOVE16,
+ ACPI_RSC_MOVE32,
+ ACPI_RSC_MOVE64,
+ ACPI_RSC_SET8,
+ ACPI_RSC_SOURCE,
+ ACPI_RSC_SOURCEX
+} ACPI_RSCONVERT_OPCODES;
/* Resource Conversion sub-opcodes */
@@ -106,6 +118,9 @@ typedef const struct acpi_rsconvert_info {
#define ACPI_RS_OFFSET(f) (u8) ACPI_OFFSET (struct acpi_resource,f)
#define AML_OFFSET(f) (u8) ACPI_OFFSET (union aml_resource,f)
+/*
+ * Individual entry for the resource dump tables
+ */
typedef const struct acpi_rsdump_info {
u8 opcode;
u8 offset;
@@ -116,20 +131,25 @@ typedef const struct acpi_rsdump_info {
/* Values for the Opcode field above */
-#define ACPI_RSD_TITLE 0
-#define ACPI_RSD_LITERAL 1
-#define ACPI_RSD_STRING 2
-#define ACPI_RSD_UINT8 3
-#define ACPI_RSD_UINT16 4
-#define ACPI_RSD_UINT32 5
-#define ACPI_RSD_UINT64 6
-#define ACPI_RSD_1BITFLAG 7
-#define ACPI_RSD_2BITFLAG 8
-#define ACPI_RSD_SHORTLIST 9
-#define ACPI_RSD_LONGLIST 10
-#define ACPI_RSD_DWORDLIST 11
-#define ACPI_RSD_ADDRESS 12
-#define ACPI_RSD_SOURCE 13
+typedef enum {
+ ACPI_RSD_TITLE = 0,
+ ACPI_RSD_1BITFLAG,
+ ACPI_RSD_2BITFLAG,
+ ACPI_RSD_3BITFLAG,
+ ACPI_RSD_ADDRESS,
+ ACPI_RSD_DWORDLIST,
+ ACPI_RSD_LITERAL,
+ ACPI_RSD_LONGLIST,
+ ACPI_RSD_SHORTLIST,
+ ACPI_RSD_SHORTLISTX,
+ ACPI_RSD_SOURCE,
+ ACPI_RSD_STRING,
+ ACPI_RSD_UINT8,
+ ACPI_RSD_UINT16,
+ ACPI_RSD_UINT32,
+ ACPI_RSD_UINT64,
+ ACPI_RSD_WORDLIST
+} ACPI_RSDUMP_OPCODES;
/* restore default alignment */
@@ -138,13 +158,18 @@ typedef const struct acpi_rsdump_info {
/* Resource tables indexed by internal resource type */
extern const u8 acpi_gbl_aml_resource_sizes[];
+extern const u8 acpi_gbl_aml_resource_serial_bus_sizes[];
extern struct acpi_rsconvert_info *acpi_gbl_set_resource_dispatch[];
/* Resource tables indexed by raw AML resource descriptor type */
extern const u8 acpi_gbl_resource_struct_sizes[];
+extern const u8 acpi_gbl_resource_struct_serial_bus_sizes[];
extern struct acpi_rsconvert_info *acpi_gbl_get_resource_dispatch[];
+extern struct acpi_rsconvert_info
+ *acpi_gbl_convert_resource_serial_bus_dispatch[];
+
struct acpi_vendor_walk_info {
struct acpi_vendor_uuid *uuid;
struct acpi_buffer *buffer;
@@ -190,6 +215,10 @@ acpi_status
acpi_rs_set_srs_method_data(struct acpi_namespace_node *node,
struct acpi_buffer *ret_buffer);
+acpi_status
+acpi_rs_get_aei_method_data(struct acpi_namespace_node *node,
+ struct acpi_buffer *ret_buffer);
+
/*
* rscalc
*/
@@ -293,6 +322,11 @@ extern struct acpi_rsconvert_info acpi_rs_convert_address16[];
extern struct acpi_rsconvert_info acpi_rs_convert_ext_irq[];
extern struct acpi_rsconvert_info acpi_rs_convert_address64[];
extern struct acpi_rsconvert_info acpi_rs_convert_ext_address64[];
+extern struct acpi_rsconvert_info acpi_rs_convert_gpio[];
+extern struct acpi_rsconvert_info acpi_rs_convert_fixed_dma[];
+extern struct acpi_rsconvert_info acpi_rs_convert_i2c_serial_bus[];
+extern struct acpi_rsconvert_info acpi_rs_convert_spi_serial_bus[];
+extern struct acpi_rsconvert_info acpi_rs_convert_uart_serial_bus[];
/* These resources require separate get/set tables */
@@ -310,6 +344,7 @@ extern struct acpi_rsconvert_info acpi_rs_set_vendor[];
* rsinfo
*/
extern struct acpi_rsdump_info *acpi_gbl_dump_resource_dispatch[];
+extern struct acpi_rsdump_info *acpi_gbl_dump_serial_bus_dispatch[];
/*
* rsdump
@@ -331,6 +366,12 @@ extern struct acpi_rsdump_info acpi_rs_dump_address64[];
extern struct acpi_rsdump_info acpi_rs_dump_ext_address64[];
extern struct acpi_rsdump_info acpi_rs_dump_ext_irq[];
extern struct acpi_rsdump_info acpi_rs_dump_generic_reg[];
+extern struct acpi_rsdump_info acpi_rs_dump_gpio[];
+extern struct acpi_rsdump_info acpi_rs_dump_fixed_dma[];
+extern struct acpi_rsdump_info acpi_rs_dump_common_serial_bus[];
+extern struct acpi_rsdump_info acpi_rs_dump_i2c_serial_bus[];
+extern struct acpi_rsdump_info acpi_rs_dump_spi_serial_bus[];
+extern struct acpi_rsdump_info acpi_rs_dump_uart_serial_bus[];
#endif
#endif /* __ACRESRC_H__ */
diff --git a/drivers/acpi/acpica/acstruct.h b/drivers/acpi/acpica/acstruct.h
index 1623b245dde2..0404df605bc1 100644
--- a/drivers/acpi/acpica/acstruct.h
+++ b/drivers/acpi/acpica/acstruct.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/actables.h b/drivers/acpi/acpica/actables.h
index 967f08124eba..d5bec304c823 100644
--- a/drivers/acpi/acpica/actables.h
+++ b/drivers/acpi/acpica/actables.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h
index 99c140d8e348..925ccf22101b 100644
--- a/drivers/acpi/acpica/acutils.h
+++ b/drivers/acpi/acpica/acutils.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -45,6 +45,7 @@
#define _ACUTILS_H
extern const u8 acpi_gbl_resource_aml_sizes[];
+extern const u8 acpi_gbl_resource_aml_serial_bus_sizes[];
/* Strings used by the disassembler and debugger resource dump routines */
@@ -579,6 +580,24 @@ acpi_ut_create_list(char *list_name,
#endif /* ACPI_DBG_TRACK_ALLOCATIONS */
/*
+ * utaddress - address range check
+ */
+acpi_status
+acpi_ut_add_address_range(acpi_adr_space_type space_id,
+ acpi_physical_address address,
+ u32 length, struct acpi_namespace_node *region_node);
+
+void
+acpi_ut_remove_address_range(acpi_adr_space_type space_id,
+ struct acpi_namespace_node *region_node);
+
+u32
+acpi_ut_check_address_range(acpi_adr_space_type space_id,
+ acpi_physical_address address, u32 length, u8 warn);
+
+void acpi_ut_delete_address_lists(void);
+
+/*
* utxferror - various error/warning output functions
*/
void ACPI_INTERNAL_VAR_XFACE
diff --git a/drivers/acpi/acpica/amlcode.h b/drivers/acpi/acpica/amlcode.h
index 1077f17859ed..905280fec0fa 100644
--- a/drivers/acpi/acpica/amlcode.h
+++ b/drivers/acpi/acpica/amlcode.h
@@ -7,7 +7,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -189,6 +189,14 @@
#define AML_LNOTEQUAL_OP (u16) 0x9293
/*
+ * Opcodes for "Field" operators
+ */
+#define AML_FIELD_OFFSET_OP (u8) 0x00
+#define AML_FIELD_ACCESS_OP (u8) 0x01
+#define AML_FIELD_CONNECTION_OP (u8) 0x02 /* ACPI 5.0 */
+#define AML_FIELD_EXT_ACCESS_OP (u8) 0x03 /* ACPI 5.0 */
+
+/*
* Internal opcodes
* Use only "Unknown" AML opcodes, don't attempt to use
* any valid ACPI ASCII values (A-Z, 0-9, '-')
@@ -202,6 +210,8 @@
#define AML_INT_METHODCALL_OP (u16) 0x0035
#define AML_INT_RETURN_VALUE_OP (u16) 0x0036
#define AML_INT_EVAL_SUBTREE_OP (u16) 0x0037
+#define AML_INT_CONNECTION_OP (u16) 0x0038
+#define AML_INT_EXTACCESSFIELD_OP (u16) 0x0039
#define ARG_NONE 0x0
@@ -456,13 +466,16 @@ typedef enum {
* access_as keyword
*/
typedef enum {
- AML_FIELD_ATTRIB_SMB_QUICK = 0x02,
- AML_FIELD_ATTRIB_SMB_SEND_RCV = 0x04,
- AML_FIELD_ATTRIB_SMB_BYTE = 0x06,
- AML_FIELD_ATTRIB_SMB_WORD = 0x08,
- AML_FIELD_ATTRIB_SMB_BLOCK = 0x0A,
- AML_FIELD_ATTRIB_SMB_WORD_CALL = 0x0C,
- AML_FIELD_ATTRIB_SMB_BLOCK_CALL = 0x0D
+ AML_FIELD_ATTRIB_QUICK = 0x02,
+ AML_FIELD_ATTRIB_SEND_RCV = 0x04,
+ AML_FIELD_ATTRIB_BYTE = 0x06,
+ AML_FIELD_ATTRIB_WORD = 0x08,
+ AML_FIELD_ATTRIB_BLOCK = 0x0A,
+ AML_FIELD_ATTRIB_MULTIBYTE = 0x0B,
+ AML_FIELD_ATTRIB_WORD_CALL = 0x0C,
+ AML_FIELD_ATTRIB_BLOCK_CALL = 0x0D,
+ AML_FIELD_ATTRIB_RAW_BYTES = 0x0E,
+ AML_FIELD_ATTRIB_RAW_PROCESS = 0x0F
} AML_ACCESS_ATTRIBUTE;
/* Bit fields in the AML method_flags byte */
diff --git a/drivers/acpi/acpica/amlresrc.h b/drivers/acpi/acpica/amlresrc.h
index 59122cde247c..7b2128f274e7 100644
--- a/drivers/acpi/acpica/amlresrc.h
+++ b/drivers/acpi/acpica/amlresrc.h
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -58,29 +58,48 @@
#define ACPI_RESTAG_TYPESPECIFICATTRIBUTES "_ATT"
#define ACPI_RESTAG_BASEADDRESS "_BAS"
#define ACPI_RESTAG_BUSMASTER "_BM_" /* Master(1), Slave(0) */
+#define ACPI_RESTAG_DEBOUNCETIME "_DBT"
#define ACPI_RESTAG_DECODE "_DEC"
+#define ACPI_RESTAG_DEVICEPOLARITY "_DPL"
#define ACPI_RESTAG_DMA "_DMA"
#define ACPI_RESTAG_DMATYPE "_TYP" /* Compatible(0), A(1), B(2), F(3) */
+#define ACPI_RESTAG_DRIVESTRENGTH "_DRS"
+#define ACPI_RESTAG_ENDIANNESS "_END"
+#define ACPI_RESTAG_FLOWCONTROL "_FLC"
#define ACPI_RESTAG_GRANULARITY "_GRA"
#define ACPI_RESTAG_INTERRUPT "_INT"
#define ACPI_RESTAG_INTERRUPTLEVEL "_LL_" /* active_lo(1), active_hi(0) */
#define ACPI_RESTAG_INTERRUPTSHARE "_SHR" /* Shareable(1), no_share(0) */
#define ACPI_RESTAG_INTERRUPTTYPE "_HE_" /* Edge(1), Level(0) */
+#define ACPI_RESTAG_IORESTRICTION "_IOR"
#define ACPI_RESTAG_LENGTH "_LEN"
+#define ACPI_RESTAG_LINE "_LIN"
#define ACPI_RESTAG_MEMATTRIBUTES "_MTP" /* Memory(0), Reserved(1), ACPI(2), NVS(3) */
#define ACPI_RESTAG_MEMTYPE "_MEM" /* non_cache(0), Cacheable(1) Cache+combine(2), Cache+prefetch(3) */
#define ACPI_RESTAG_MAXADDR "_MAX"
#define ACPI_RESTAG_MINADDR "_MIN"
#define ACPI_RESTAG_MAXTYPE "_MAF"
#define ACPI_RESTAG_MINTYPE "_MIF"
+#define ACPI_RESTAG_MODE "_MOD"
+#define ACPI_RESTAG_PARITY "_PAR"
+#define ACPI_RESTAG_PHASE "_PHA"
+#define ACPI_RESTAG_PIN "_PIN"
+#define ACPI_RESTAG_PINCONFIG "_PPI"
+#define ACPI_RESTAG_POLARITY "_POL"
#define ACPI_RESTAG_REGISTERBITOFFSET "_RBO"
#define ACPI_RESTAG_REGISTERBITWIDTH "_RBW"
#define ACPI_RESTAG_RANGETYPE "_RNG"
#define ACPI_RESTAG_READWRITETYPE "_RW_" /* read_only(0), Writeable (1) */
+#define ACPI_RESTAG_LENGTH_RX "_RXL"
+#define ACPI_RESTAG_LENGTH_TX "_TXL"
+#define ACPI_RESTAG_SLAVEMODE "_SLV"
+#define ACPI_RESTAG_SPEED "_SPE"
+#define ACPI_RESTAG_STOPBITS "_STB"
#define ACPI_RESTAG_TRANSLATION "_TRA"
#define ACPI_RESTAG_TRANSTYPE "_TRS" /* Sparse(1), Dense(0) */
#define ACPI_RESTAG_TYPE "_TTP" /* Translation(1), Static (0) */
#define ACPI_RESTAG_XFERTYPE "_SIZ" /* 8(0), 8_and16(1), 16(2) */
+#define ACPI_RESTAG_VENDORDATA "_VEN"
/* Default sizes for "small" resource descriptors */
@@ -90,6 +109,7 @@
#define ASL_RDESC_END_DEPEND_SIZE 0x00
#define ASL_RDESC_IO_SIZE 0x07
#define ASL_RDESC_FIXED_IO_SIZE 0x03
+#define ASL_RDESC_FIXED_DMA_SIZE 0x05
#define ASL_RDESC_END_TAG_SIZE 0x01
struct asl_resource_node {
@@ -164,6 +184,12 @@ struct aml_resource_end_tag {
AML_RESOURCE_SMALL_HEADER_COMMON u8 checksum;
};
+struct aml_resource_fixed_dma {
+ AML_RESOURCE_SMALL_HEADER_COMMON u16 request_lines;
+ u16 channels;
+ u8 width;
+};
+
/*
* LARGE descriptors
*/
@@ -263,6 +289,110 @@ struct aml_resource_generic_register {
u64 address;
};
+/* Common descriptor for gpio_int and gpio_io (ACPI 5.0) */
+
+struct aml_resource_gpio {
+ AML_RESOURCE_LARGE_HEADER_COMMON u8 revision_id;
+ u8 connection_type;
+ u16 flags;
+ u16 int_flags;
+ u8 pin_config;
+ u16 drive_strength;
+ u16 debounce_timeout;
+ u16 pin_table_offset;
+ u8 res_source_index;
+ u16 res_source_offset;
+ u16 vendor_offset;
+ u16 vendor_length;
+ /*
+ * Optional fields follow immediately:
+ * 1) PIN list (Words)
+ * 2) Resource Source String
+ * 3) Vendor Data bytes
+ */
+};
+
+#define AML_RESOURCE_GPIO_REVISION 1 /* ACPI 5.0 */
+
+/* Values for connection_type above */
+
+#define AML_RESOURCE_GPIO_TYPE_INT 0
+#define AML_RESOURCE_GPIO_TYPE_IO 1
+#define AML_RESOURCE_MAX_GPIOTYPE 1
+
+/* Common preamble for all serial descriptors (ACPI 5.0) */
+
+#define AML_RESOURCE_SERIAL_COMMON \
+ u8 revision_id; \
+ u8 res_source_index; \
+ u8 type; \
+ u8 flags; \
+ u16 type_specific_flags; \
+ u8 type_revision_id; \
+ u16 type_data_length; \
+
+/* Values for the type field above */
+
+#define AML_RESOURCE_I2C_SERIALBUSTYPE 1
+#define AML_RESOURCE_SPI_SERIALBUSTYPE 2
+#define AML_RESOURCE_UART_SERIALBUSTYPE 3
+#define AML_RESOURCE_MAX_SERIALBUSTYPE 3
+#define AML_RESOURCE_VENDOR_SERIALBUSTYPE 192 /* Vendor defined is 0xC0-0xFF (NOT SUPPORTED) */
+
+struct aml_resource_common_serialbus {
+AML_RESOURCE_LARGE_HEADER_COMMON AML_RESOURCE_SERIAL_COMMON};
+
+struct aml_resource_i2c_serialbus {
+ AML_RESOURCE_LARGE_HEADER_COMMON
+ AML_RESOURCE_SERIAL_COMMON u32 connection_speed;
+ u16 slave_address;
+ /*
+ * Optional fields follow immediately:
+ * 1) Vendor Data bytes
+ * 2) Resource Source String
+ */
+};
+
+#define AML_RESOURCE_I2C_REVISION 1 /* ACPI 5.0 */
+#define AML_RESOURCE_I2C_TYPE_REVISION 1 /* ACPI 5.0 */
+#define AML_RESOURCE_I2C_MIN_DATA_LEN 6
+
+struct aml_resource_spi_serialbus {
+ AML_RESOURCE_LARGE_HEADER_COMMON
+ AML_RESOURCE_SERIAL_COMMON u32 connection_speed;
+ u8 data_bit_length;
+ u8 clock_phase;
+ u8 clock_polarity;
+ u16 device_selection;
+ /*
+ * Optional fields follow immediately:
+ * 1) Vendor Data bytes
+ * 2) Resource Source String
+ */
+};
+
+#define AML_RESOURCE_SPI_REVISION 1 /* ACPI 5.0 */
+#define AML_RESOURCE_SPI_TYPE_REVISION 1 /* ACPI 5.0 */
+#define AML_RESOURCE_SPI_MIN_DATA_LEN 9
+
+struct aml_resource_uart_serialbus {
+ AML_RESOURCE_LARGE_HEADER_COMMON
+ AML_RESOURCE_SERIAL_COMMON u32 default_baud_rate;
+ u16 rx_fifo_size;
+ u16 tx_fifo_size;
+ u8 parity;
+ u8 lines_enabled;
+ /*
+ * Optional fields follow immediately:
+ * 1) Vendor Data bytes
+ * 2) Resource Source String
+ */
+};
+
+#define AML_RESOURCE_UART_REVISION 1 /* ACPI 5.0 */
+#define AML_RESOURCE_UART_TYPE_REVISION 1 /* ACPI 5.0 */
+#define AML_RESOURCE_UART_MIN_DATA_LEN 10
+
/* restore default alignment */
#pragma pack()
@@ -284,6 +414,7 @@ union aml_resource {
struct aml_resource_end_dependent end_dpf;
struct aml_resource_io io;
struct aml_resource_fixed_io fixed_io;
+ struct aml_resource_fixed_dma fixed_dma;
struct aml_resource_vendor_small vendor_small;
struct aml_resource_end_tag end_tag;
@@ -299,6 +430,11 @@ union aml_resource {
struct aml_resource_address64 address64;
struct aml_resource_extended_address64 ext_address64;
struct aml_resource_extended_irq extended_irq;
+ struct aml_resource_gpio gpio;
+ struct aml_resource_i2c_serialbus i2c_serial_bus;
+ struct aml_resource_spi_serialbus spi_serial_bus;
+ struct aml_resource_uart_serialbus uart_serial_bus;
+ struct aml_resource_common_serialbus common_serial_bus;
/* Utility overlays */
diff --git a/drivers/acpi/acpica/dsargs.c b/drivers/acpi/acpica/dsargs.c
index 8c7b99728aa2..80eb1900297f 100644
--- a/drivers/acpi/acpica/dsargs.c
+++ b/drivers/acpi/acpica/dsargs.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -250,6 +250,13 @@ acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc)
status = acpi_ds_execute_arguments(node, node->parent,
extra_desc->extra.aml_length,
extra_desc->extra.aml_start);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ status = acpi_ut_add_address_range(obj_desc->region.space_id,
+ obj_desc->region.address,
+ obj_desc->region.length, node);
return_ACPI_STATUS(status);
}
@@ -384,8 +391,15 @@ acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc)
/* Execute the argument AML */
- status = acpi_ds_execute_arguments(node, node->parent,
+ status = acpi_ds_execute_arguments(node, extra_desc->extra.scope_node,
extra_desc->extra.aml_length,
extra_desc->extra.aml_start);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ status = acpi_ut_add_address_range(obj_desc->region.space_id,
+ obj_desc->region.address,
+ obj_desc->region.length, node);
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/acpica/dscontrol.c b/drivers/acpi/acpica/dscontrol.c
index 26c49fff58da..effe4ca1133f 100644
--- a/drivers/acpi/acpica/dscontrol.c
+++ b/drivers/acpi/acpica/dscontrol.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c
index 34be60c0e448..cd243cf2cab2 100644
--- a/drivers/acpi/acpica/dsfield.c
+++ b/drivers/acpi/acpica/dsfield.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -221,6 +221,7 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
{
acpi_status status;
u64 position;
+ union acpi_parse_object *child;
ACPI_FUNCTION_TRACE_PTR(ds_get_field_names, info);
@@ -232,10 +233,11 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
while (arg) {
/*
- * Three types of field elements are handled:
- * 1) Offset - specifies a bit offset
- * 2) access_as - changes the access mode
- * 3) Name - Enters a new named field into the namespace
+ * Four types of field elements are handled:
+ * 1) Name - Enters a new named field into the namespace
+ * 2) Offset - specifies a bit offset
+ * 3) access_as - changes the access mode/attributes
+ * 4) Connection - Associate a resource template with the field
*/
switch (arg->common.aml_opcode) {
case AML_INT_RESERVEDFIELD_OP:
@@ -253,21 +255,70 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
break;
case AML_INT_ACCESSFIELD_OP:
-
+ case AML_INT_EXTACCESSFIELD_OP:
/*
- * Get a new access_type and access_attribute -- to be used for all
- * field units that follow, until field end or another access_as
- * keyword.
+ * Get new access_type, access_attribute, and access_length fields
+ * -- to be used for all field units that follow, until the
+ * end-of-field or another access_as keyword is encountered.
+ * NOTE. These three bytes are encoded in the integer value
+ * of the parseop for convenience.
*
* In field_flags, preserve the flag bits other than the
- * ACCESS_TYPE bits
+ * ACCESS_TYPE bits.
*/
+
+ /* access_type (byte_acc, word_acc, etc.) */
+
info->field_flags = (u8)
((info->
field_flags & ~(AML_FIELD_ACCESS_TYPE_MASK)) |
- ((u8) ((u32) arg->common.value.integer >> 8)));
+ ((u8)((u32)(arg->common.value.integer & 0x07))));
+
+ /* access_attribute (attrib_quick, attrib_byte, etc.) */
+
+ info->attribute =
+ (u8)((arg->common.value.integer >> 8) & 0xFF);
+
+ /* access_length (for serial/buffer protocols) */
+
+ info->access_length =
+ (u8)((arg->common.value.integer >> 16) & 0xFF);
+ break;
+
+ case AML_INT_CONNECTION_OP:
+ /*
+ * Clear any previous connection. New connection is used for all
+ * fields that follow, similar to access_as
+ */
+ info->resource_buffer = NULL;
+ info->connection_node = NULL;
- info->attribute = (u8) (arg->common.value.integer);
+ /*
+ * A Connection() is either an actual resource descriptor (buffer)
+ * or a named reference to a resource template
+ */
+ child = arg->common.value.arg;
+ if (child->common.aml_opcode == AML_INT_BYTELIST_OP) {
+ info->resource_buffer = child->named.data;
+ info->resource_length =
+ (u16)child->named.value.integer;
+ } else {
+ /* Lookup the Connection() namepath, it should already exist */
+
+ status = acpi_ns_lookup(walk_state->scope_info,
+ child->common.value.
+ name, ACPI_TYPE_ANY,
+ ACPI_IMODE_EXECUTE,
+ ACPI_NS_DONT_OPEN_SCOPE,
+ walk_state,
+ &info->connection_node);
+ if (ACPI_FAILURE(status)) {
+ ACPI_ERROR_NAMESPACE(child->common.
+ value.name,
+ status);
+ return_ACPI_STATUS(status);
+ }
+ }
break;
case AML_INT_NAMEDFIELD_OP:
@@ -374,6 +425,8 @@ acpi_ds_create_field(union acpi_parse_object *op,
}
}
+ ACPI_MEMSET(&info, 0, sizeof(struct acpi_create_field_info));
+
/* Second arg is the field flags */
arg = arg->common.next;
@@ -386,7 +439,6 @@ acpi_ds_create_field(union acpi_parse_object *op,
info.region_node = region_node;
status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
-
return_ACPI_STATUS(status);
}
@@ -474,8 +526,8 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
*/
while (arg) {
/*
- * Ignore OFFSET and ACCESSAS terms here; we are only interested in the
- * field names in order to enter them into the namespace.
+ * Ignore OFFSET/ACCESSAS/CONNECTION terms here; we are only interested
+ * in the field names in order to enter them into the namespace.
*/
if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
status = acpi_ns_lookup(walk_state->scope_info,
@@ -651,6 +703,5 @@ acpi_ds_create_index_field(union acpi_parse_object *op,
info.region_node = region_node;
status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
-
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/acpica/dsinit.c b/drivers/acpi/acpica/dsinit.c
index a7718bf2b9a1..9e5ac7f780a7 100644
--- a/drivers/acpi/acpica/dsinit.c
+++ b/drivers/acpi/acpica/dsinit.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c
index 5d797751e205..00f5dab5bcc0 100644
--- a/drivers/acpi/acpica/dsmethod.c
+++ b/drivers/acpi/acpica/dsmethod.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/dsmthdat.c b/drivers/acpi/acpica/dsmthdat.c
index 905ce29a92e1..b40bd507be5d 100644
--- a/drivers/acpi/acpica/dsmthdat.c
+++ b/drivers/acpi/acpica/dsmthdat.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/dsobject.c b/drivers/acpi/acpica/dsobject.c
index f42e17e5c252..d7045ca3e32a 100644
--- a/drivers/acpi/acpica/dsobject.c
+++ b/drivers/acpi/acpica/dsobject.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c
index c627a288e027..e5eff7585102 100644
--- a/drivers/acpi/acpica/dsopcode.c
+++ b/drivers/acpi/acpica/dsopcode.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/dsutils.c b/drivers/acpi/acpica/dsutils.c
index 2c477ce172fa..1abcda31037f 100644
--- a/drivers/acpi/acpica/dsutils.c
+++ b/drivers/acpi/acpica/dsutils.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/dswexec.c b/drivers/acpi/acpica/dswexec.c
index fe40e4c6554f..642f3c053e87 100644
--- a/drivers/acpi/acpica/dswexec.c
+++ b/drivers/acpi/acpica/dswexec.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/dswload.c b/drivers/acpi/acpica/dswload.c
index 324acec1179a..552aa3a50c84 100644
--- a/drivers/acpi/acpica/dswload.c
+++ b/drivers/acpi/acpica/dswload.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/dswload2.c b/drivers/acpi/acpica/dswload2.c
index 976318138c56..ae7147724763 100644
--- a/drivers/acpi/acpica/dswload2.c
+++ b/drivers/acpi/acpica/dswload2.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/dswscope.c b/drivers/acpi/acpica/dswscope.c
index 76a661fc1e09..9e9490a9cbf0 100644
--- a/drivers/acpi/acpica/dswscope.c
+++ b/drivers/acpi/acpica/dswscope.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/dswstate.c b/drivers/acpi/acpica/dswstate.c
index a6c374ef9914..c9c2ac13e7cc 100644
--- a/drivers/acpi/acpica/dswstate.c
+++ b/drivers/acpi/acpica/dswstate.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/evevent.c b/drivers/acpi/acpica/evevent.c
index d458b041e651..6729ebe2f1e6 100644
--- a/drivers/acpi/acpica/evevent.c
+++ b/drivers/acpi/acpica/evevent.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -71,6 +71,12 @@ acpi_status acpi_ev_initialize_events(void)
ACPI_FUNCTION_TRACE(ev_initialize_events);
+ /* If Hardware Reduced flag is set, there are no fixed events */
+
+ if (acpi_gbl_reduced_hardware) {
+ return_ACPI_STATUS(AE_OK);
+ }
+
/*
* Initialize the Fixed and General Purpose Events. This is done prior to
* enabling SCIs to prevent interrupts from occurring before the handlers
@@ -111,6 +117,12 @@ acpi_status acpi_ev_install_xrupt_handlers(void)
ACPI_FUNCTION_TRACE(ev_install_xrupt_handlers);
+ /* If Hardware Reduced flag is set, there is no ACPI h/w */
+
+ if (acpi_gbl_reduced_hardware) {
+ return_ACPI_STATUS(AE_OK);
+ }
+
/* Install the SCI handler */
status = acpi_ev_install_sci_handler();
diff --git a/drivers/acpi/acpica/evglock.c b/drivers/acpi/acpica/evglock.c
index 56a562a1e5d7..5e5683cb1f0d 100644
--- a/drivers/acpi/acpica/evglock.c
+++ b/drivers/acpi/acpica/evglock.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -70,6 +70,12 @@ acpi_status acpi_ev_init_global_lock_handler(void)
ACPI_FUNCTION_TRACE(ev_init_global_lock_handler);
+ /* If Hardware Reduced flag is set, there is no global lock */
+
+ if (acpi_gbl_reduced_hardware) {
+ return_ACPI_STATUS(AE_OK);
+ }
+
/* Attempt installation of the global lock handler */
status = acpi_install_fixed_event_handler(ACPI_EVENT_GLOBAL,
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c
index 65c79add3b19..9e88cb6fb25e 100644
--- a/drivers/acpi/acpica/evgpe.c
+++ b/drivers/acpi/acpica/evgpe.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c
index ca2c41a53311..be75339cd5dd 100644
--- a/drivers/acpi/acpica/evgpeblk.c
+++ b/drivers/acpi/acpica/evgpeblk.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/evgpeinit.c b/drivers/acpi/acpica/evgpeinit.c
index ce9aa9f9a972..adf7494da9db 100644
--- a/drivers/acpi/acpica/evgpeinit.c
+++ b/drivers/acpi/acpica/evgpeinit.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/evgpeutil.c b/drivers/acpi/acpica/evgpeutil.c
index 80a81d0c4a80..25073932aa10 100644
--- a/drivers/acpi/acpica/evgpeutil.c
+++ b/drivers/acpi/acpica/evgpeutil.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c
index d0b331844427..84966f416463 100644
--- a/drivers/acpi/acpica/evmisc.c
+++ b/drivers/acpi/acpica/evmisc.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c
index f0edf5c43c03..1b0180a1b798 100644
--- a/drivers/acpi/acpica/evregion.c
+++ b/drivers/acpi/acpica/evregion.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -329,6 +329,7 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function)
* FUNCTION: acpi_ev_address_space_dispatch
*
* PARAMETERS: region_obj - Internal region object
+ * field_obj - Corresponding field. Can be NULL.
* Function - Read or Write operation
* region_offset - Where in the region to read or write
* bit_width - Field width in bits (8, 16, 32, or 64)
@@ -344,6 +345,7 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function)
acpi_status
acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
+ union acpi_operand_object *field_obj,
u32 function,
u32 region_offset, u32 bit_width, u64 *value)
{
@@ -353,6 +355,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
union acpi_operand_object *handler_desc;
union acpi_operand_object *region_obj2;
void *region_context = NULL;
+ struct acpi_connection_info *context;
ACPI_FUNCTION_TRACE(ev_address_space_dispatch);
@@ -375,6 +378,8 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
return_ACPI_STATUS(AE_NOT_EXIST);
}
+ context = handler_desc->address_space.context;
+
/*
* It may be the case that the region has never been initialized.
* Some types of regions require special init code
@@ -404,8 +409,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
acpi_ex_exit_interpreter();
status = region_setup(region_obj, ACPI_REGION_ACTIVATE,
- handler_desc->address_space.context,
- &region_context);
+ context, &region_context);
/* Re-enter the interpreter */
@@ -455,6 +459,25 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
acpi_ut_get_region_name(region_obj->region.
space_id)));
+ /*
+ * Special handling for generic_serial_bus and general_purpose_io:
+ * There are three extra parameters that must be passed to the
+ * handler via the context:
+ * 1) Connection buffer, a resource template from Connection() op.
+ * 2) Length of the above buffer.
+ * 3) Actual access length from the access_as() op.
+ */
+ if (((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) ||
+ (region_obj->region.space_id == ACPI_ADR_SPACE_GPIO)) &&
+ context && field_obj) {
+
+ /* Get the Connection (resource_template) buffer */
+
+ context->connection = field_obj->field.resource_buffer;
+ context->length = field_obj->field.resource_length;
+ context->access_length = field_obj->field.access_length;
+ }
+
if (!(handler_desc->address_space.handler_flags &
ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
/*
@@ -469,7 +492,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
status = handler(function,
(region_obj->region.address + region_offset),
- bit_width, value, handler_desc->address_space.context,
+ bit_width, value, context,
region_obj2->extra.region_context);
if (ACPI_FAILURE(status)) {
diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c
index 55a5d35ef34a..819c17f5897a 100644
--- a/drivers/acpi/acpica/evrgnini.c
+++ b/drivers/acpi/acpica/evrgnini.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/evsci.c b/drivers/acpi/acpica/evsci.c
index 2ebd40e1a3ef..26065c612e76 100644
--- a/drivers/acpi/acpica/evsci.c
+++ b/drivers/acpi/acpica/evsci.c
@@ -6,7 +6,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c
index f4f523bf5939..61944e89565a 100644
--- a/drivers/acpi/acpica/evxface.c
+++ b/drivers/acpi/acpica/evxface.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c
index 20516e599476..1768bbec1002 100644
--- a/drivers/acpi/acpica/evxfevnt.c
+++ b/drivers/acpi/acpica/evxfevnt.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c
index f06a3ee356ba..33388fd69df4 100644
--- a/drivers/acpi/acpica/evxfgpe.c
+++ b/drivers/acpi/acpica/evxfgpe.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c
index aee887e3ca5c..6019208cd4b6 100644
--- a/drivers/acpi/acpica/evxfregn.c
+++ b/drivers/acpi/acpica/evxfregn.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c
index 745a42b401f5..c86d44e41bc8 100644
--- a/drivers/acpi/acpica/exconfig.c
+++ b/drivers/acpi/acpica/exconfig.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -297,9 +297,9 @@ acpi_ex_region_read(union acpi_operand_object *obj_desc, u32 length, u8 *buffer)
/* Bytewise reads */
for (i = 0; i < length; i++) {
- status = acpi_ev_address_space_dispatch(obj_desc, ACPI_READ,
- region_offset, 8,
- &value);
+ status =
+ acpi_ev_address_space_dispatch(obj_desc, NULL, ACPI_READ,
+ region_offset, 8, &value);
if (ACPI_FAILURE(status)) {
return status;
}
diff --git a/drivers/acpi/acpica/exconvrt.c b/drivers/acpi/acpica/exconvrt.c
index 74162a11817d..e385436bd424 100644
--- a/drivers/acpi/acpica/exconvrt.c
+++ b/drivers/acpi/acpica/exconvrt.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/excreate.c b/drivers/acpi/acpica/excreate.c
index 110711afada8..3f5bc998c1cb 100644
--- a/drivers/acpi/acpica/excreate.c
+++ b/drivers/acpi/acpica/excreate.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -267,7 +267,7 @@ acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state)
*
* PARAMETERS: aml_start - Pointer to the region declaration AML
* aml_length - Max length of the declaration AML
- * region_space - space_iD for the region
+ * space_id - Address space ID for the region
* walk_state - Current state
*
* RETURN: Status
@@ -279,7 +279,7 @@ acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state)
acpi_status
acpi_ex_create_region(u8 * aml_start,
u32 aml_length,
- u8 region_space, struct acpi_walk_state *walk_state)
+ u8 space_id, struct acpi_walk_state *walk_state)
{
acpi_status status;
union acpi_operand_object *obj_desc;
@@ -304,16 +304,19 @@ acpi_ex_create_region(u8 * aml_start,
* Space ID must be one of the predefined IDs, or in the user-defined
* range
*/
- if ((region_space >= ACPI_NUM_PREDEFINED_REGIONS) &&
- (region_space < ACPI_USER_REGION_BEGIN) &&
- (region_space != ACPI_ADR_SPACE_DATA_TABLE)) {
- ACPI_ERROR((AE_INFO, "Invalid AddressSpace type 0x%X",
- region_space));
- return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID);
+ if (!acpi_is_valid_space_id(space_id)) {
+ /*
+ * Print an error message, but continue. We don't want to abort
+ * a table load for this exception. Instead, if the region is
+ * actually used at runtime, abort the executing method.
+ */
+ ACPI_ERROR((AE_INFO,
+ "Invalid/unknown Address Space ID: 0x%2.2X",
+ space_id));
}
ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Region Type - %s (0x%X)\n",
- acpi_ut_get_region_name(region_space), region_space));
+ acpi_ut_get_region_name(space_id), space_id));
/* Create the region descriptor */
@@ -330,10 +333,16 @@ acpi_ex_create_region(u8 * aml_start,
region_obj2 = obj_desc->common.next_object;
region_obj2->extra.aml_start = aml_start;
region_obj2->extra.aml_length = aml_length;
+ if (walk_state->scope_info) {
+ region_obj2->extra.scope_node =
+ walk_state->scope_info->scope.node;
+ } else {
+ region_obj2->extra.scope_node = node;
+ }
/* Init the region from the operands */
- obj_desc->region.space_id = region_space;
+ obj_desc->region.space_id = space_id;
obj_desc->region.address = 0;
obj_desc->region.length = 0;
obj_desc->region.node = node;
diff --git a/drivers/acpi/acpica/exdebug.c b/drivers/acpi/acpica/exdebug.c
index c7a2f1edd282..e211e9c19215 100644
--- a/drivers/acpi/acpica/exdebug.c
+++ b/drivers/acpi/acpica/exdebug.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exdump.c b/drivers/acpi/acpica/exdump.c
index 61b8c0e8b74d..2a6ac0a3bc1e 100644
--- a/drivers/acpi/acpica/exdump.c
+++ b/drivers/acpi/acpica/exdump.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -192,10 +192,13 @@ static struct acpi_exdump_info acpi_ex_dump_buffer_field[3] = {
"Buffer Object"}
};
-static struct acpi_exdump_info acpi_ex_dump_region_field[3] = {
+static struct acpi_exdump_info acpi_ex_dump_region_field[5] = {
{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_region_field), NULL},
{ACPI_EXD_FIELD, 0, NULL},
- {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(field.region_obj), "Region Object"}
+ {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(field.access_length), "AccessLength"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(field.region_obj), "Region Object"},
+ {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(field.resource_buffer),
+ "ResourceBuffer"}
};
static struct acpi_exdump_info acpi_ex_dump_bank_field[5] = {
diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c
index 0bde2230c028..dc092f5b35d6 100644
--- a/drivers/acpi/acpica/exfield.c
+++ b/drivers/acpi/acpica/exfield.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -100,18 +100,25 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
(obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_SMBUS
|| obj_desc->field.region_obj->region.space_id ==
+ ACPI_ADR_SPACE_GSBUS
+ || obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_IPMI)) {
/*
- * This is an SMBus or IPMI read. We must create a buffer to hold
+ * This is an SMBus, GSBus or IPMI read. We must create a buffer to hold
* the data and then directly access the region handler.
*
- * Note: Smbus protocol value is passed in upper 16-bits of Function
+ * Note: SMBus and GSBus protocol value is passed in upper 16-bits of Function
*/
if (obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_SMBUS) {
length = ACPI_SMBUS_BUFFER_SIZE;
function =
ACPI_READ | (obj_desc->field.attribute << 16);
+ } else if (obj_desc->field.region_obj->region.space_id ==
+ ACPI_ADR_SPACE_GSBUS) {
+ length = ACPI_GSBUS_BUFFER_SIZE;
+ function =
+ ACPI_READ | (obj_desc->field.attribute << 16);
} else { /* IPMI */
length = ACPI_IPMI_BUFFER_SIZE;
@@ -248,21 +255,23 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
(obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_SMBUS
|| obj_desc->field.region_obj->region.space_id ==
+ ACPI_ADR_SPACE_GSBUS
+ || obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_IPMI)) {
/*
- * This is an SMBus or IPMI write. We will bypass the entire field
+ * This is an SMBus, GSBus or IPMI write. We will bypass the entire field
* mechanism and handoff the buffer directly to the handler. For
* these address spaces, the buffer is bi-directional; on a write,
* return data is returned in the same buffer.
*
* Source must be a buffer of sufficient size:
- * ACPI_SMBUS_BUFFER_SIZE or ACPI_IPMI_BUFFER_SIZE.
+ * ACPI_SMBUS_BUFFER_SIZE, ACPI_GSBUS_BUFFER_SIZE, or ACPI_IPMI_BUFFER_SIZE.
*
- * Note: SMBus protocol type is passed in upper 16-bits of Function
+ * Note: SMBus and GSBus protocol type is passed in upper 16-bits of Function
*/
if (source_desc->common.type != ACPI_TYPE_BUFFER) {
ACPI_ERROR((AE_INFO,
- "SMBus or IPMI write requires Buffer, found type %s",
+ "SMBus/IPMI/GenericSerialBus write requires Buffer, found type %s",
acpi_ut_get_object_type_name(source_desc)));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
@@ -273,6 +282,11 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
length = ACPI_SMBUS_BUFFER_SIZE;
function =
ACPI_WRITE | (obj_desc->field.attribute << 16);
+ } else if (obj_desc->field.region_obj->region.space_id ==
+ ACPI_ADR_SPACE_GSBUS) {
+ length = ACPI_GSBUS_BUFFER_SIZE;
+ function =
+ ACPI_WRITE | (obj_desc->field.attribute << 16);
} else { /* IPMI */
length = ACPI_IPMI_BUFFER_SIZE;
@@ -281,7 +295,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
if (source_desc->buffer.length < length) {
ACPI_ERROR((AE_INFO,
- "SMBus or IPMI write requires Buffer of length %u, found length %u",
+ "SMBus/IPMI/GenericSerialBus write requires Buffer of length %u, found length %u",
length, source_desc->buffer.length));
return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c
index f915a7f3f921..149de45fdadd 100644
--- a/drivers/acpi/acpica/exfldio.c
+++ b/drivers/acpi/acpica/exfldio.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -86,6 +86,7 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
{
acpi_status status = AE_OK;
union acpi_operand_object *rgn_desc;
+ u8 space_id;
ACPI_FUNCTION_TRACE_U32(ex_setup_region, field_datum_byte_offset);
@@ -101,6 +102,17 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
+ space_id = rgn_desc->region.space_id;
+
+ /* Validate the Space ID */
+
+ if (!acpi_is_valid_space_id(space_id)) {
+ ACPI_ERROR((AE_INFO,
+ "Invalid/unknown Address Space ID: 0x%2.2X",
+ space_id));
+ return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID);
+ }
+
/*
* If the Region Address and Length have not been previously evaluated,
* evaluate them now and save the results.
@@ -119,11 +131,12 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
}
/*
- * Exit now for SMBus or IPMI address space, it has a non-linear
+ * Exit now for SMBus, GSBus or IPMI address space, it has a non-linear
* address space and the request cannot be directly validated
*/
- if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS ||
- rgn_desc->region.space_id == ACPI_ADR_SPACE_IPMI) {
+ if (space_id == ACPI_ADR_SPACE_SMBUS ||
+ space_id == ACPI_ADR_SPACE_GSBUS ||
+ space_id == ACPI_ADR_SPACE_IPMI) {
/* SMBus or IPMI has a non-linear address space */
@@ -271,11 +284,12 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc,
/* Invoke the appropriate address_space/op_region handler */
- status =
- acpi_ev_address_space_dispatch(rgn_desc, function, region_offset,
- ACPI_MUL_8(obj_desc->common_field.
- access_byte_width),
- value);
+ status = acpi_ev_address_space_dispatch(rgn_desc, obj_desc,
+ function, region_offset,
+ ACPI_MUL_8(obj_desc->
+ common_field.
+ access_byte_width),
+ value);
if (ACPI_FAILURE(status)) {
if (status == AE_NOT_IMPLEMENTED) {
@@ -316,6 +330,7 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc,
static u8
acpi_ex_register_overflow(union acpi_operand_object *obj_desc, u64 value)
{
+ ACPI_FUNCTION_NAME(ex_register_overflow);
if (obj_desc->common_field.bit_length >= ACPI_INTEGER_BIT_SIZE) {
/*
@@ -330,6 +345,11 @@ acpi_ex_register_overflow(union acpi_operand_object *obj_desc, u64 value)
* The Value is larger than the maximum value that can fit into
* the register.
*/
+ ACPI_ERROR((AE_INFO,
+ "Index value 0x%8.8X%8.8X overflows field width 0x%X",
+ ACPI_FORMAT_UINT64(value),
+ obj_desc->common_field.bit_length));
+
return (TRUE);
}
diff --git a/drivers/acpi/acpica/exmisc.c b/drivers/acpi/acpica/exmisc.c
index 703d88ed0b3d..0a0893310348 100644
--- a/drivers/acpi/acpica/exmisc.c
+++ b/drivers/acpi/acpica/exmisc.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exmutex.c b/drivers/acpi/acpica/exmutex.c
index be1c56ead653..60933e9dc3c0 100644
--- a/drivers/acpi/acpica/exmutex.c
+++ b/drivers/acpi/acpica/exmutex.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exnames.c b/drivers/acpi/acpica/exnames.c
index 49ec049c157e..fcc75fa27d32 100644
--- a/drivers/acpi/acpica/exnames.c
+++ b/drivers/acpi/acpica/exnames.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exoparg1.c b/drivers/acpi/acpica/exoparg1.c
index 236ead14b7f7..9ba8c73cea16 100644
--- a/drivers/acpi/acpica/exoparg1.c
+++ b/drivers/acpi/acpica/exoparg1.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exoparg2.c b/drivers/acpi/acpica/exoparg2.c
index 2571b4a310f4..879e8a277b94 100644
--- a/drivers/acpi/acpica/exoparg2.c
+++ b/drivers/acpi/acpica/exoparg2.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exoparg3.c b/drivers/acpi/acpica/exoparg3.c
index 1b48d9d28c9a..71fcc65c9ffa 100644
--- a/drivers/acpi/acpica/exoparg3.c
+++ b/drivers/acpi/acpica/exoparg3.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exoparg6.c b/drivers/acpi/acpica/exoparg6.c
index f4a2787e8e92..0786b8659061 100644
--- a/drivers/acpi/acpica/exoparg6.c
+++ b/drivers/acpi/acpica/exoparg6.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c
index cc95e2000406..30157f5a12d7 100644
--- a/drivers/acpi/acpica/exprep.c
+++ b/drivers/acpi/acpica/exprep.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -47,6 +47,7 @@
#include "acinterp.h"
#include "amlcode.h"
#include "acnamesp.h"
+#include "acdispat.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exprep")
@@ -455,6 +456,30 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
obj_desc->field.region_obj =
acpi_ns_get_attached_object(info->region_node);
+ /* Fields specific to generic_serial_bus fields */
+
+ obj_desc->field.access_length = info->access_length;
+
+ if (info->connection_node) {
+ second_desc = info->connection_node->object;
+ if (!(second_desc->common.flags & AOPOBJ_DATA_VALID)) {
+ status =
+ acpi_ds_get_buffer_arguments(second_desc);
+ if (ACPI_FAILURE(status)) {
+ acpi_ut_delete_object_desc(obj_desc);
+ return_ACPI_STATUS(status);
+ }
+ }
+
+ obj_desc->field.resource_buffer =
+ second_desc->buffer.pointer;
+ obj_desc->field.resource_length =
+ (u16)second_desc->buffer.length;
+ } else if (info->resource_buffer) {
+ obj_desc->field.resource_buffer = info->resource_buffer;
+ obj_desc->field.resource_length = info->resource_length;
+ }
+
/* Allow full data read from EC address space */
if ((obj_desc->field.region_obj->region.space_id ==
diff --git a/drivers/acpi/acpica/exregion.c b/drivers/acpi/acpica/exregion.c
index f0d5e14f1f2c..12d51df6d3bf 100644
--- a/drivers/acpi/acpica/exregion.c
+++ b/drivers/acpi/acpica/exregion.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exresnte.c b/drivers/acpi/acpica/exresnte.c
index 55997e46948b..fa50e77e64a8 100644
--- a/drivers/acpi/acpica/exresnte.c
+++ b/drivers/acpi/acpica/exresnte.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exresolv.c b/drivers/acpi/acpica/exresolv.c
index db502cd7d934..6e335dc34528 100644
--- a/drivers/acpi/acpica/exresolv.c
+++ b/drivers/acpi/acpica/exresolv.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exresop.c b/drivers/acpi/acpica/exresop.c
index e3bb00ccdff5..a67b1d925ddd 100644
--- a/drivers/acpi/acpica/exresop.c
+++ b/drivers/acpi/acpica/exresop.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exstore.c b/drivers/acpi/acpica/exstore.c
index c0c8842dd344..c6cf843cc4c9 100644
--- a/drivers/acpi/acpica/exstore.c
+++ b/drivers/acpi/acpica/exstore.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exstoren.c b/drivers/acpi/acpica/exstoren.c
index a979017d56b8..b35bed52e061 100644
--- a/drivers/acpi/acpica/exstoren.c
+++ b/drivers/acpi/acpica/exstoren.c
@@ -7,7 +7,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exstorob.c b/drivers/acpi/acpica/exstorob.c
index dc665cc554de..65a45d8335c8 100644
--- a/drivers/acpi/acpica/exstorob.c
+++ b/drivers/acpi/acpica/exstorob.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exsystem.c b/drivers/acpi/acpica/exsystem.c
index df66e7b686be..191a12945226 100644
--- a/drivers/acpi/acpica/exsystem.c
+++ b/drivers/acpi/acpica/exsystem.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/exutils.c b/drivers/acpi/acpica/exutils.c
index 8ad93146dd32..eb6798ba8b59 100644
--- a/drivers/acpi/acpica/exutils.c
+++ b/drivers/acpi/acpica/exutils.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -435,4 +435,29 @@ void acpi_ex_integer_to_string(char *out_string, u64 value)
}
}
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_is_valid_space_id
+ *
+ * PARAMETERS: space_id - ID to be validated
+ *
+ * RETURN: TRUE if valid/supported ID.
+ *
+ * DESCRIPTION: Validate an operation region space_iD.
+ *
+ ******************************************************************************/
+
+u8 acpi_is_valid_space_id(u8 space_id)
+{
+
+ if ((space_id >= ACPI_NUM_PREDEFINED_REGIONS) &&
+ (space_id < ACPI_USER_REGION_BEGIN) &&
+ (space_id != ACPI_ADR_SPACE_DATA_TABLE) &&
+ (space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) {
+ return (FALSE);
+ }
+
+ return (TRUE);
+}
+
#endif
diff --git a/drivers/acpi/acpica/hwacpi.c b/drivers/acpi/acpica/hwacpi.c
index fc380d3d45ab..d21ec5f0b3a9 100644
--- a/drivers/acpi/acpica/hwacpi.c
+++ b/drivers/acpi/acpica/hwacpi.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c
index f610d88a66be..1a6894afef79 100644
--- a/drivers/acpi/acpica/hwgpe.c
+++ b/drivers/acpi/acpica/hwgpe.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/hwpci.c b/drivers/acpi/acpica/hwpci.c
index 050fd227951b..1455ddcdc32c 100644
--- a/drivers/acpi/acpica/hwpci.c
+++ b/drivers/acpi/acpica/hwpci.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c
index cc70f3fdcdd1..4ea4eeb51bfd 100644
--- a/drivers/acpi/acpica/hwregs.c
+++ b/drivers/acpi/acpica/hwregs.c
@@ -7,7 +7,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c
index d52da3073650..3c4a922a9fc2 100644
--- a/drivers/acpi/acpica/hwsleep.c
+++ b/drivers/acpi/acpica/hwsleep.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/hwtimer.c b/drivers/acpi/acpica/hwtimer.c
index 50d21c40b5c1..d4973d9da9f1 100644
--- a/drivers/acpi/acpica/hwtimer.c
+++ b/drivers/acpi/acpica/hwtimer.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/hwvalid.c b/drivers/acpi/acpica/hwvalid.c
index 5f1605874655..6e5c43a60bb7 100644
--- a/drivers/acpi/acpica/hwvalid.c
+++ b/drivers/acpi/acpica/hwvalid.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -134,6 +134,8 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width)
/* Supported widths are 8/16/32 */
if ((bit_width != 8) && (bit_width != 16) && (bit_width != 32)) {
+ ACPI_ERROR((AE_INFO,
+ "Bad BitWidth parameter: %8.8X", bit_width));
return AE_BAD_PARAMETER;
}
diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c
index d707756228c2..9d38eb6c0d0b 100644
--- a/drivers/acpi/acpica/hwxface.c
+++ b/drivers/acpi/acpica/hwxface.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nsaccess.c b/drivers/acpi/acpica/nsaccess.c
index d93172fd15a8..61623f3f6826 100644
--- a/drivers/acpi/acpica/nsaccess.c
+++ b/drivers/acpi/acpica/nsaccess.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nsalloc.c b/drivers/acpi/acpica/nsalloc.c
index 1d0ef15d158f..7c3d3ceb98b3 100644
--- a/drivers/acpi/acpica/nsalloc.c
+++ b/drivers/acpi/acpica/nsalloc.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c
index b683cc2ff9d3..b7f2b3be79ac 100644
--- a/drivers/acpi/acpica/nsdump.c
+++ b/drivers/acpi/acpica/nsdump.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nsdumpdv.c b/drivers/acpi/acpica/nsdumpdv.c
index 2ed294b7a4db..30ea5bc53a78 100644
--- a/drivers/acpi/acpica/nsdumpdv.c
+++ b/drivers/acpi/acpica/nsdumpdv.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nseval.c b/drivers/acpi/acpica/nseval.c
index c1bd02b1a058..f375cb82e321 100644
--- a/drivers/acpi/acpica/nseval.c
+++ b/drivers/acpi/acpica/nseval.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nsinit.c b/drivers/acpi/acpica/nsinit.c
index fd7c6380e294..9d84ec2f0211 100644
--- a/drivers/acpi/acpica/nsinit.c
+++ b/drivers/acpi/acpica/nsinit.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nsload.c b/drivers/acpi/acpica/nsload.c
index 5f7dc691c183..5cbf15ffe7d8 100644
--- a/drivers/acpi/acpica/nsload.c
+++ b/drivers/acpi/acpica/nsload.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nsnames.c b/drivers/acpi/acpica/nsnames.c
index d5fa520c3de5..b20e7c8c3ffb 100644
--- a/drivers/acpi/acpica/nsnames.c
+++ b/drivers/acpi/acpica/nsnames.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nsobject.c b/drivers/acpi/acpica/nsobject.c
index 3bb8bf105ea2..dd77a3ce6e50 100644
--- a/drivers/acpi/acpica/nsobject.c
+++ b/drivers/acpi/acpica/nsobject.c
@@ -6,7 +6,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nsparse.c b/drivers/acpi/acpica/nsparse.c
index b3234fa795b8..ec7ba2d3463c 100644
--- a/drivers/acpi/acpica/nsparse.c
+++ b/drivers/acpi/acpica/nsparse.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c
index c845c8089f39..bbe46a447d34 100644
--- a/drivers/acpi/acpica/nspredef.c
+++ b/drivers/acpi/acpica/nspredef.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -620,6 +620,7 @@ acpi_ns_check_package(struct acpi_predefined_data *data,
case ACPI_PTYPE2_FIXED:
case ACPI_PTYPE2_MIN:
case ACPI_PTYPE2_COUNT:
+ case ACPI_PTYPE2_FIX_VAR:
/*
* These types all return a single Package that consists of a
@@ -759,6 +760,34 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data,
}
break;
+ case ACPI_PTYPE2_FIX_VAR:
+ /*
+ * Each subpackage has a fixed number of elements and an
+ * optional element
+ */
+ expected_count =
+ package->ret_info.count1 + package->ret_info.count2;
+ if (sub_package->package.count < expected_count) {
+ goto package_too_small;
+ }
+
+ status =
+ acpi_ns_check_package_elements(data, sub_elements,
+ package->ret_info.
+ object_type1,
+ package->ret_info.
+ count1,
+ package->ret_info.
+ object_type2,
+ sub_package->package.
+ count -
+ package->ret_info.
+ count1, 0);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+ break;
+
case ACPI_PTYPE2_FIXED:
/* Each sub-package has a fixed length */
diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c
index ac7b854b0bd7..9c35d20eb52b 100644
--- a/drivers/acpi/acpica/nsrepair.c
+++ b/drivers/acpi/acpica/nsrepair.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -634,6 +634,7 @@ acpi_ns_remove_null_elements(struct acpi_predefined_data *data,
case ACPI_PTYPE2_FIXED:
case ACPI_PTYPE2_MIN:
case ACPI_PTYPE2_REV_FIXED:
+ case ACPI_PTYPE2_FIX_VAR:
break;
default:
diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c
index 024c4f263f87..726bc8e687f7 100644
--- a/drivers/acpi/acpica/nsrepair2.c
+++ b/drivers/acpi/acpica/nsrepair2.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -467,11 +467,12 @@ acpi_ns_repair_HID(struct acpi_predefined_data *data,
}
/*
- * Copy and uppercase the string. From the ACPI specification:
+ * Copy and uppercase the string. From the ACPI 5.0 specification:
*
* A valid PNP ID must be of the form "AAA####" where A is an uppercase
* letter and # is a hex digit. A valid ACPI ID must be of the form
- * "ACPI####" where # is a hex digit.
+ * "NNNN####" where N is an uppercase letter or decimal digit, and
+ * # is a hex digit.
*/
for (dest = new_string->string.pointer; *source; dest++, source++) {
*dest = (char)ACPI_TOUPPER(*source);
diff --git a/drivers/acpi/acpica/nssearch.c b/drivers/acpi/acpica/nssearch.c
index 28b0d7a62b99..507043d66114 100644
--- a/drivers/acpi/acpica/nssearch.c
+++ b/drivers/acpi/acpica/nssearch.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nsutils.c b/drivers/acpi/acpica/nsutils.c
index cb1b104a69a2..a535b7afda5c 100644
--- a/drivers/acpi/acpica/nsutils.c
+++ b/drivers/acpi/acpica/nsutils.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nswalk.c b/drivers/acpi/acpica/nswalk.c
index 345f0c3c6ad2..f69895a54895 100644
--- a/drivers/acpi/acpica/nswalk.c
+++ b/drivers/acpi/acpica/nswalk.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c
index e7f016d1b226..71d15f61807b 100644
--- a/drivers/acpi/acpica/nsxfeval.c
+++ b/drivers/acpi/acpica/nsxfeval.c
@@ -6,7 +6,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nsxfname.c b/drivers/acpi/acpica/nsxfname.c
index 83bf93024303..af401c9c4dfc 100644
--- a/drivers/acpi/acpica/nsxfname.c
+++ b/drivers/acpi/acpica/nsxfname.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/nsxfobj.c b/drivers/acpi/acpica/nsxfobj.c
index 57e6d825ed84..880a605cee20 100644
--- a/drivers/acpi/acpica/nsxfobj.c
+++ b/drivers/acpi/acpica/nsxfobj.c
@@ -6,7 +6,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/psargs.c b/drivers/acpi/acpica/psargs.c
index e1fad0ee0136..5ac36aba507c 100644
--- a/drivers/acpi/acpica/psargs.c
+++ b/drivers/acpi/acpica/psargs.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -484,34 +484,54 @@ acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state,
static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
*parser_state)
{
- u32 aml_offset = (u32)
- ACPI_PTR_DIFF(parser_state->aml,
- parser_state->aml_start);
+ u32 aml_offset;
union acpi_parse_object *field;
+ union acpi_parse_object *arg = NULL;
u16 opcode;
u32 name;
+ u8 access_type;
+ u8 access_attribute;
+ u8 access_length;
+ u32 pkg_length;
+ u8 *pkg_end;
+ u32 buffer_length;
ACPI_FUNCTION_TRACE(ps_get_next_field);
+ aml_offset =
+ (u32)ACPI_PTR_DIFF(parser_state->aml, parser_state->aml_start);
+
/* Determine field type */
switch (ACPI_GET8(parser_state->aml)) {
- default:
+ case AML_FIELD_OFFSET_OP:
- opcode = AML_INT_NAMEDFIELD_OP;
+ opcode = AML_INT_RESERVEDFIELD_OP;
+ parser_state->aml++;
break;
- case 0x00:
+ case AML_FIELD_ACCESS_OP:
- opcode = AML_INT_RESERVEDFIELD_OP;
+ opcode = AML_INT_ACCESSFIELD_OP;
parser_state->aml++;
break;
- case 0x01:
+ case AML_FIELD_CONNECTION_OP:
- opcode = AML_INT_ACCESSFIELD_OP;
+ opcode = AML_INT_CONNECTION_OP;
+ parser_state->aml++;
+ break;
+
+ case AML_FIELD_EXT_ACCESS_OP:
+
+ opcode = AML_INT_EXTACCESSFIELD_OP;
parser_state->aml++;
break;
+
+ default:
+
+ opcode = AML_INT_NAMEDFIELD_OP;
+ break;
}
/* Allocate a new field op */
@@ -549,16 +569,111 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
break;
case AML_INT_ACCESSFIELD_OP:
+ case AML_INT_EXTACCESSFIELD_OP:
/*
* Get access_type and access_attrib and merge into the field Op
- * access_type is first operand, access_attribute is second
+ * access_type is first operand, access_attribute is second. stuff
+ * these bytes into the node integer value for convenience.
*/
- field->common.value.integer =
- (((u32) ACPI_GET8(parser_state->aml) << 8));
+
+ /* Get the two bytes (Type/Attribute) */
+
+ access_type = ACPI_GET8(parser_state->aml);
parser_state->aml++;
- field->common.value.integer |= ACPI_GET8(parser_state->aml);
+ access_attribute = ACPI_GET8(parser_state->aml);
parser_state->aml++;
+
+ field->common.value.integer = (u8)access_type;
+ field->common.value.integer |= (u16)(access_attribute << 8);
+
+ /* This opcode has a third byte, access_length */
+
+ if (opcode == AML_INT_EXTACCESSFIELD_OP) {
+ access_length = ACPI_GET8(parser_state->aml);
+ parser_state->aml++;
+
+ field->common.value.integer |=
+ (u32)(access_length << 16);
+ }
+ break;
+
+ case AML_INT_CONNECTION_OP:
+
+ /*
+ * Argument for Connection operator can be either a Buffer
+ * (resource descriptor), or a name_string.
+ */
+ if (ACPI_GET8(parser_state->aml) == AML_BUFFER_OP) {
+ parser_state->aml++;
+
+ pkg_end = parser_state->aml;
+ pkg_length =
+ acpi_ps_get_next_package_length(parser_state);
+ pkg_end += pkg_length;
+
+ if (parser_state->aml < pkg_end) {
+
+ /* Non-empty list */
+
+ arg = acpi_ps_alloc_op(AML_INT_BYTELIST_OP);
+ if (!arg) {
+ return_PTR(NULL);
+ }
+
+ /* Get the actual buffer length argument */
+
+ opcode = ACPI_GET8(parser_state->aml);
+ parser_state->aml++;
+
+ switch (opcode) {
+ case AML_BYTE_OP: /* AML_BYTEDATA_ARG */
+ buffer_length =
+ ACPI_GET8(parser_state->aml);
+ parser_state->aml += 1;
+ break;
+
+ case AML_WORD_OP: /* AML_WORDDATA_ARG */
+ buffer_length =
+ ACPI_GET16(parser_state->aml);
+ parser_state->aml += 2;
+ break;
+
+ case AML_DWORD_OP: /* AML_DWORDATA_ARG */
+ buffer_length =
+ ACPI_GET32(parser_state->aml);
+ parser_state->aml += 4;
+ break;
+
+ default:
+ buffer_length = 0;
+ break;
+ }
+
+ /* Fill in bytelist data */
+
+ arg->named.value.size = buffer_length;
+ arg->named.data = parser_state->aml;
+ }
+
+ /* Skip to End of byte data */
+
+ parser_state->aml = pkg_end;
+ } else {
+ arg = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP);
+ if (!arg) {
+ return_PTR(NULL);
+ }
+
+ /* Get the Namestring argument */
+
+ arg->common.value.name =
+ acpi_ps_get_next_namestring(parser_state);
+ }
+
+ /* Link the buffer/namestring to parent (CONNECTION_OP) */
+
+ acpi_ps_append_arg(field, arg);
break;
default:
diff --git a/drivers/acpi/acpica/psloop.c b/drivers/acpi/acpica/psloop.c
index 01dd70d1de51..9547ad8a620b 100644
--- a/drivers/acpi/acpica/psloop.c
+++ b/drivers/acpi/acpica/psloop.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/psopcode.c b/drivers/acpi/acpica/psopcode.c
index bed08de7528c..a0226fdcf75c 100644
--- a/drivers/acpi/acpica/psopcode.c
+++ b/drivers/acpi/acpica/psopcode.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -638,7 +638,16 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = {
/* 7E */ ACPI_OP("Timer", ARGP_TIMER_OP, ARGI_TIMER_OP, ACPI_TYPE_ANY,
AML_CLASS_EXECUTE, AML_TYPE_EXEC_0A_0T_1R,
- AML_FLAGS_EXEC_0A_0T_1R)
+ AML_FLAGS_EXEC_0A_0T_1R),
+
+/* ACPI 5.0 opcodes */
+
+/* 7F */ ACPI_OP("-ConnectField-", ARGP_CONNECTFIELD_OP,
+ ARGI_CONNECTFIELD_OP, ACPI_TYPE_ANY,
+ AML_CLASS_INTERNAL, AML_TYPE_BOGUS, AML_HAS_ARGS),
+/* 80 */ ACPI_OP("-ExtAccessField-", ARGP_CONNECTFIELD_OP,
+ ARGI_CONNECTFIELD_OP, ACPI_TYPE_ANY,
+ AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0)
/*! [End] no source code translation !*/
};
@@ -657,7 +666,7 @@ static const u8 acpi_gbl_short_op_index[256] = {
/* 0x20 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
/* 0x28 */ _UNK, _UNK, _UNK, _UNK, _UNK, 0x63, _PFX, _PFX,
/* 0x30 */ 0x67, 0x66, 0x68, 0x65, 0x69, 0x64, 0x6A, 0x7D,
-/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x38 */ 0x7F, 0x80, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
/* 0x40 */ _UNK, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
/* 0x48 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
/* 0x50 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
diff --git a/drivers/acpi/acpica/psparse.c b/drivers/acpi/acpica/psparse.c
index 9bb0cbd37b5e..2ff9c35a1968 100644
--- a/drivers/acpi/acpica/psparse.c
+++ b/drivers/acpi/acpica/psparse.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/psscope.c b/drivers/acpi/acpica/psscope.c
index a5faa1323a02..c872aa4b926e 100644
--- a/drivers/acpi/acpica/psscope.c
+++ b/drivers/acpi/acpica/psscope.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/pstree.c b/drivers/acpi/acpica/pstree.c
index f1464c03aa42..2b03cdbbe1c0 100644
--- a/drivers/acpi/acpica/pstree.c
+++ b/drivers/acpi/acpica/pstree.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -74,6 +74,12 @@ union acpi_parse_object *acpi_ps_get_arg(union acpi_parse_object *op, u32 argn)
ACPI_FUNCTION_ENTRY();
+/*
+ if (Op->Common.aml_opcode == AML_INT_CONNECTION_OP)
+ {
+ return (Op->Common.Value.Arg);
+ }
+*/
/* Get the info structure for this opcode */
op_info = acpi_ps_get_opcode_info(op->common.aml_opcode);
diff --git a/drivers/acpi/acpica/psutils.c b/drivers/acpi/acpica/psutils.c
index 7eda78503422..13bb131ae125 100644
--- a/drivers/acpi/acpica/psutils.c
+++ b/drivers/acpi/acpica/psutils.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/pswalk.c b/drivers/acpi/acpica/pswalk.c
index 3312d6368bf1..ab96cf47896d 100644
--- a/drivers/acpi/acpica/pswalk.c
+++ b/drivers/acpi/acpica/pswalk.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/psxface.c b/drivers/acpi/acpica/psxface.c
index 8086805d4494..9d98c5ff66a5 100644
--- a/drivers/acpi/acpica/psxface.c
+++ b/drivers/acpi/acpica/psxface.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/rsaddr.c b/drivers/acpi/acpica/rsaddr.c
index 9e66f9078426..a0305652394f 100644
--- a/drivers/acpi/acpica/rsaddr.c
+++ b/drivers/acpi/acpica/rsaddr.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/rscalc.c b/drivers/acpi/acpica/rscalc.c
index 3a8a89ec2ca4..3c6df4b7eb2d 100644
--- a/drivers/acpi/acpica/rscalc.c
+++ b/drivers/acpi/acpica/rscalc.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -313,6 +313,38 @@ acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed)
resource_source));
break;
+ case ACPI_RESOURCE_TYPE_GPIO:
+
+ total_size =
+ (acpi_rs_length) (total_size +
+ (resource->data.gpio.
+ pin_table_length * 2) +
+ resource->data.gpio.
+ resource_source.string_length +
+ resource->data.gpio.
+ vendor_length);
+
+ break;
+
+ case ACPI_RESOURCE_TYPE_SERIAL_BUS:
+
+ total_size =
+ acpi_gbl_aml_resource_serial_bus_sizes[resource->
+ data.
+ common_serial_bus.
+ type];
+
+ total_size = (acpi_rs_length) (total_size +
+ resource->data.
+ i2c_serial_bus.
+ resource_source.
+ string_length +
+ resource->data.
+ i2c_serial_bus.
+ vendor_length);
+
+ break;
+
default:
break;
}
@@ -362,10 +394,11 @@ acpi_rs_get_list_length(u8 * aml_buffer,
u32 extra_struct_bytes;
u8 resource_index;
u8 minimum_aml_resource_length;
+ union aml_resource *aml_resource;
ACPI_FUNCTION_TRACE(rs_get_list_length);
- *size_needed = 0;
+ *size_needed = ACPI_RS_SIZE_MIN; /* Minimum size is one end_tag */
end_aml = aml_buffer + aml_buffer_length;
/* Walk the list of AML resource descriptors */
@@ -376,9 +409,15 @@ acpi_rs_get_list_length(u8 * aml_buffer,
status = acpi_ut_validate_resource(aml_buffer, &resource_index);
if (ACPI_FAILURE(status)) {
+ /*
+ * Exit on failure. Cannot continue because the descriptor length
+ * may be bogus also.
+ */
return_ACPI_STATUS(status);
}
+ aml_resource = (void *)aml_buffer;
+
/* Get the resource length and base (minimum) AML size */
resource_length = acpi_ut_get_resource_length(aml_buffer);
@@ -422,10 +461,8 @@ acpi_rs_get_list_length(u8 * aml_buffer,
case ACPI_RESOURCE_NAME_END_TAG:
/*
- * End Tag:
- * This is the normal exit, add size of end_tag
+ * End Tag: This is the normal exit
*/
- *size_needed += ACPI_RS_SIZE_MIN;
return_ACPI_STATUS(AE_OK);
case ACPI_RESOURCE_NAME_ADDRESS32:
@@ -457,6 +494,33 @@ acpi_rs_get_list_length(u8 * aml_buffer,
minimum_aml_resource_length);
break;
+ case ACPI_RESOURCE_NAME_GPIO:
+
+ /* Vendor data is optional */
+
+ if (aml_resource->gpio.vendor_length) {
+ extra_struct_bytes +=
+ aml_resource->gpio.vendor_offset -
+ aml_resource->gpio.pin_table_offset +
+ aml_resource->gpio.vendor_length;
+ } else {
+ extra_struct_bytes +=
+ aml_resource->large_header.resource_length +
+ sizeof(struct aml_resource_large_header) -
+ aml_resource->gpio.pin_table_offset;
+ }
+ break;
+
+ case ACPI_RESOURCE_NAME_SERIAL_BUS:
+
+ minimum_aml_resource_length =
+ acpi_gbl_resource_aml_serial_bus_sizes
+ [aml_resource->common_serial_bus.type];
+ extra_struct_bytes +=
+ aml_resource->common_serial_bus.resource_length -
+ minimum_aml_resource_length;
+ break;
+
default:
break;
}
@@ -467,9 +531,18 @@ acpi_rs_get_list_length(u8 * aml_buffer,
* Important: Round the size up for the appropriate alignment. This
* is a requirement on IA64.
*/
- buffer_size = acpi_gbl_resource_struct_sizes[resource_index] +
- extra_struct_bytes;
- buffer_size = (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(buffer_size);
+ if (acpi_ut_get_resource_type(aml_buffer) ==
+ ACPI_RESOURCE_NAME_SERIAL_BUS) {
+ buffer_size =
+ acpi_gbl_resource_struct_serial_bus_sizes
+ [aml_resource->common_serial_bus.type] +
+ extra_struct_bytes;
+ } else {
+ buffer_size =
+ acpi_gbl_resource_struct_sizes[resource_index] +
+ extra_struct_bytes;
+ }
+ buffer_size = (u32)ACPI_ROUND_UP_TO_NATIVE_WORD(buffer_size);
*size_needed += buffer_size;
diff --git a/drivers/acpi/acpica/rscreate.c b/drivers/acpi/acpica/rscreate.c
index 4ce6e1147e80..46d6eb38ae66 100644
--- a/drivers/acpi/acpica/rscreate.c
+++ b/drivers/acpi/acpica/rscreate.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -51,6 +51,70 @@ ACPI_MODULE_NAME("rscreate")
/*******************************************************************************
*
+ * FUNCTION: acpi_buffer_to_resource
+ *
+ * PARAMETERS: aml_buffer - Pointer to the resource byte stream
+ * aml_buffer_length - Length of the aml_buffer
+ * resource_ptr - Where the converted resource is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Convert a raw AML buffer to a resource list
+ *
+ ******************************************************************************/
+acpi_status
+acpi_buffer_to_resource(u8 *aml_buffer,
+ u16 aml_buffer_length,
+ struct acpi_resource **resource_ptr)
+{
+ acpi_status status;
+ acpi_size list_size_needed;
+ void *resource;
+ void *current_resource_ptr;
+
+ /*
+ * Note: we allow AE_AML_NO_RESOURCE_END_TAG, since an end tag
+ * is not required here.
+ */
+
+ /* Get the required length for the converted resource */
+
+ status = acpi_rs_get_list_length(aml_buffer, aml_buffer_length,
+ &list_size_needed);
+ if (status == AE_AML_NO_RESOURCE_END_TAG) {
+ status = AE_OK;
+ }
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ /* Allocate a buffer for the converted resource */
+
+ resource = ACPI_ALLOCATE_ZEROED(list_size_needed);
+ current_resource_ptr = resource;
+ if (!resource) {
+ return (AE_NO_MEMORY);
+ }
+
+ /* Perform the AML-to-Resource conversion */
+
+ status = acpi_ut_walk_aml_resources(aml_buffer, aml_buffer_length,
+ acpi_rs_convert_aml_to_resources,
+ &current_resource_ptr);
+ if (status == AE_AML_NO_RESOURCE_END_TAG) {
+ status = AE_OK;
+ }
+ if (ACPI_FAILURE(status)) {
+ ACPI_FREE(resource);
+ } else {
+ *resource_ptr = resource;
+ }
+
+ return (status);
+}
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_rs_create_resource_list
*
* PARAMETERS: aml_buffer - Pointer to the resource byte stream
@@ -66,9 +130,10 @@ ACPI_MODULE_NAME("rscreate")
* of device resources.
*
******************************************************************************/
+
acpi_status
acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer,
- struct acpi_buffer *output_buffer)
+ struct acpi_buffer * output_buffer)
{
acpi_status status;
diff --git a/drivers/acpi/acpica/rsdump.c b/drivers/acpi/acpica/rsdump.c
index 33db7520c74b..b4c581132393 100644
--- a/drivers/acpi/acpica/rsdump.c
+++ b/drivers/acpi/acpica/rsdump.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -61,11 +61,13 @@ static void acpi_rs_out_integer64(char *title, u64 value);
static void acpi_rs_out_title(char *title);
-static void acpi_rs_dump_byte_list(u16 length, u8 * data);
+static void acpi_rs_dump_byte_list(u16 length, u8 *data);
-static void acpi_rs_dump_dword_list(u8 length, u32 * data);
+static void acpi_rs_dump_word_list(u16 length, u16 *data);
-static void acpi_rs_dump_short_byte_list(u8 length, u8 * data);
+static void acpi_rs_dump_dword_list(u8 length, u32 *data);
+
+static void acpi_rs_dump_short_byte_list(u8 length, u8 *data);
static void
acpi_rs_dump_resource_source(struct acpi_resource_source *resource_source);
@@ -309,6 +311,125 @@ struct acpi_rsdump_info acpi_rs_dump_generic_reg[6] = {
{ACPI_RSD_UINT64, ACPI_RSD_OFFSET(generic_reg.address), "Address", NULL}
};
+struct acpi_rsdump_info acpi_rs_dump_gpio[16] = {
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_gpio), "GPIO", NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(gpio.revision_id), "RevisionId", NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(gpio.connection_type),
+ "ConnectionType", acpi_gbl_ct_decode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(gpio.producer_consumer),
+ "ProducerConsumer", acpi_gbl_consume_decode},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(gpio.pin_config), "PinConfig",
+ acpi_gbl_ppc_decode},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(gpio.sharable), "Sharable",
+ acpi_gbl_shr_decode},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(gpio.io_restriction),
+ "IoRestriction", acpi_gbl_ior_decode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(gpio.triggering), "Triggering",
+ acpi_gbl_he_decode},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(gpio.polarity), "Polarity",
+ acpi_gbl_ll_decode},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(gpio.drive_strength), "DriveStrength",
+ NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(gpio.debounce_timeout),
+ "DebounceTimeout", NULL},
+ {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(gpio.resource_source),
+ "ResourceSource", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(gpio.pin_table_length),
+ "PinTableLength", NULL},
+ {ACPI_RSD_WORDLIST, ACPI_RSD_OFFSET(gpio.pin_table), "PinTable", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(gpio.vendor_length), "VendorLength",
+ NULL},
+ {ACPI_RSD_SHORTLISTX, ACPI_RSD_OFFSET(gpio.vendor_data), "VendorData",
+ NULL},
+};
+
+struct acpi_rsdump_info acpi_rs_dump_fixed_dma[4] = {
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_dma),
+ "FixedDma", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(fixed_dma.request_lines),
+ "RequestLines", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(fixed_dma.channels), "Channels",
+ NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(fixed_dma.width), "TransferWidth",
+ acpi_gbl_dts_decode},
+};
+
+#define ACPI_RS_DUMP_COMMON_SERIAL_BUS \
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (common_serial_bus.revision_id), "RevisionId", NULL}, \
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (common_serial_bus.type), "Type", acpi_gbl_sbt_decode}, \
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (common_serial_bus.producer_consumer), "ProducerConsumer", acpi_gbl_consume_decode}, \
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (common_serial_bus.slave_mode), "SlaveMode", acpi_gbl_sm_decode}, \
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (common_serial_bus.type_revision_id), "TypeRevisionId", NULL}, \
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (common_serial_bus.type_data_length), "TypeDataLength", NULL}, \
+ {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (common_serial_bus.resource_source), "ResourceSource", NULL}, \
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (common_serial_bus.vendor_length), "VendorLength", NULL}, \
+ {ACPI_RSD_SHORTLISTX,ACPI_RSD_OFFSET (common_serial_bus.vendor_data), "VendorData", NULL},
+
+struct acpi_rsdump_info acpi_rs_dump_common_serial_bus[10] = {
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_common_serial_bus),
+ "Common Serial Bus", NULL},
+ ACPI_RS_DUMP_COMMON_SERIAL_BUS
+};
+
+struct acpi_rsdump_info acpi_rs_dump_i2c_serial_bus[13] = {
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_i2c_serial_bus),
+ "I2C Serial Bus", NULL},
+ ACPI_RS_DUMP_COMMON_SERIAL_BUS {ACPI_RSD_1BITFLAG,
+ ACPI_RSD_OFFSET(i2c_serial_bus.
+ access_mode),
+ "AccessMode", acpi_gbl_am_decode},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(i2c_serial_bus.connection_speed),
+ "ConnectionSpeed", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(i2c_serial_bus.slave_address),
+ "SlaveAddress", NULL},
+};
+
+struct acpi_rsdump_info acpi_rs_dump_spi_serial_bus[17] = {
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_spi_serial_bus),
+ "Spi Serial Bus", NULL},
+ ACPI_RS_DUMP_COMMON_SERIAL_BUS {ACPI_RSD_1BITFLAG,
+ ACPI_RSD_OFFSET(spi_serial_bus.
+ wire_mode), "WireMode",
+ acpi_gbl_wm_decode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(spi_serial_bus.device_polarity),
+ "DevicePolarity", acpi_gbl_dp_decode},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(spi_serial_bus.data_bit_length),
+ "DataBitLength", NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(spi_serial_bus.clock_phase),
+ "ClockPhase", acpi_gbl_cph_decode},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(spi_serial_bus.clock_polarity),
+ "ClockPolarity", acpi_gbl_cpo_decode},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(spi_serial_bus.device_selection),
+ "DeviceSelection", NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(spi_serial_bus.connection_speed),
+ "ConnectionSpeed", NULL},
+};
+
+struct acpi_rsdump_info acpi_rs_dump_uart_serial_bus[19] = {
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_uart_serial_bus),
+ "Uart Serial Bus", NULL},
+ ACPI_RS_DUMP_COMMON_SERIAL_BUS {ACPI_RSD_2BITFLAG,
+ ACPI_RSD_OFFSET(uart_serial_bus.
+ flow_control),
+ "FlowControl", acpi_gbl_fc_decode},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(uart_serial_bus.stop_bits),
+ "StopBits", acpi_gbl_sb_decode},
+ {ACPI_RSD_3BITFLAG, ACPI_RSD_OFFSET(uart_serial_bus.data_bits),
+ "DataBits", acpi_gbl_bpb_decode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(uart_serial_bus.endian), "Endian",
+ acpi_gbl_ed_decode},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(uart_serial_bus.parity), "Parity",
+ acpi_gbl_pt_decode},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(uart_serial_bus.lines_enabled),
+ "LinesEnabled", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(uart_serial_bus.rx_fifo_size),
+ "RxFifoSize", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET(uart_serial_bus.tx_fifo_size),
+ "TxFifoSize", NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET(uart_serial_bus.default_baud_rate),
+ "ConnectionSpeed", NULL},
+};
+
/*
* Tables used for common address descriptor flag fields
*/
@@ -413,7 +534,14 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table)
/* Data items, 8/16/32/64 bit */
case ACPI_RSD_UINT8:
- acpi_rs_out_integer8(name, ACPI_GET8(target));
+ if (table->pointer) {
+ acpi_rs_out_string(name, ACPI_CAST_PTR(char,
+ table->
+ pointer
+ [*target]));
+ } else {
+ acpi_rs_out_integer8(name, ACPI_GET8(target));
+ }
break;
case ACPI_RSD_UINT16:
@@ -444,6 +572,13 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table)
0x03]));
break;
+ case ACPI_RSD_3BITFLAG:
+ acpi_rs_out_string(name, ACPI_CAST_PTR(char,
+ table->
+ pointer[*target &
+ 0x07]));
+ break;
+
case ACPI_RSD_SHORTLIST:
/*
* Short byte list (single line output) for DMA and IRQ resources
@@ -456,6 +591,20 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table)
}
break;
+ case ACPI_RSD_SHORTLISTX:
+ /*
+ * Short byte list (single line output) for GPIO vendor data
+ * Note: The list length is obtained from the previous table entry
+ */
+ if (previous_target) {
+ acpi_rs_out_title(name);
+ acpi_rs_dump_short_byte_list(*previous_target,
+ *
+ (ACPI_CAST_INDIRECT_PTR
+ (u8, target)));
+ }
+ break;
+
case ACPI_RSD_LONGLIST:
/*
* Long byte list for Vendor resource data
@@ -480,6 +629,18 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table)
}
break;
+ case ACPI_RSD_WORDLIST:
+ /*
+ * Word list for GPIO Pin Table
+ * Note: The list length is obtained from the previous table entry
+ */
+ if (previous_target) {
+ acpi_rs_dump_word_list(*previous_target,
+ *(ACPI_CAST_INDIRECT_PTR
+ (u16, target)));
+ }
+ break;
+
case ACPI_RSD_ADDRESS:
/*
* Common flags for all Address resources
@@ -627,14 +788,20 @@ void acpi_rs_dump_resource_list(struct acpi_resource *resource_list)
/* Dump the resource descriptor */
- acpi_rs_dump_descriptor(&resource_list->data,
- acpi_gbl_dump_resource_dispatch[type]);
+ if (type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
+ acpi_rs_dump_descriptor(&resource_list->data,
+ acpi_gbl_dump_serial_bus_dispatch
+ [resource_list->data.
+ common_serial_bus.type]);
+ } else {
+ acpi_rs_dump_descriptor(&resource_list->data,
+ acpi_gbl_dump_resource_dispatch
+ [type]);
+ }
/* Point to the next resource structure */
- resource_list =
- ACPI_ADD_PTR(struct acpi_resource, resource_list,
- resource_list->length);
+ resource_list = ACPI_NEXT_RESOURCE(resource_list);
/* Exit when END_TAG descriptor is reached */
@@ -768,4 +935,13 @@ static void acpi_rs_dump_dword_list(u8 length, u32 * data)
}
}
+static void acpi_rs_dump_word_list(u16 length, u16 *data)
+{
+ u16 i;
+
+ for (i = 0; i < length; i++) {
+ acpi_os_printf("%25s%2.2X : %4.4X\n", "Word", i, data[i]);
+ }
+}
+
#endif
diff --git a/drivers/acpi/acpica/rsinfo.c b/drivers/acpi/acpica/rsinfo.c
index f9ea60872aa4..a9fa5158200b 100644
--- a/drivers/acpi/acpica/rsinfo.c
+++ b/drivers/acpi/acpica/rsinfo.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -76,7 +76,10 @@ struct acpi_rsconvert_info *acpi_gbl_set_resource_dispatch[] = {
acpi_rs_convert_address64, /* 0x0D, ACPI_RESOURCE_TYPE_ADDRESS64 */
acpi_rs_convert_ext_address64, /* 0x0E, ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64 */
acpi_rs_convert_ext_irq, /* 0x0F, ACPI_RESOURCE_TYPE_EXTENDED_IRQ */
- acpi_rs_convert_generic_reg /* 0x10, ACPI_RESOURCE_TYPE_GENERIC_REGISTER */
+ acpi_rs_convert_generic_reg, /* 0x10, ACPI_RESOURCE_TYPE_GENERIC_REGISTER */
+ acpi_rs_convert_gpio, /* 0x11, ACPI_RESOURCE_TYPE_GPIO */
+ acpi_rs_convert_fixed_dma, /* 0x12, ACPI_RESOURCE_TYPE_FIXED_DMA */
+ NULL, /* 0x13, ACPI_RESOURCE_TYPE_SERIAL_BUS - Use subtype table below */
};
/* Dispatch tables for AML-to-resource (Get Resource) conversion functions */
@@ -94,7 +97,7 @@ struct acpi_rsconvert_info *acpi_gbl_get_resource_dispatch[] = {
acpi_rs_convert_end_dpf, /* 0x07, ACPI_RESOURCE_NAME_END_DEPENDENT */
acpi_rs_convert_io, /* 0x08, ACPI_RESOURCE_NAME_IO */
acpi_rs_convert_fixed_io, /* 0x09, ACPI_RESOURCE_NAME_FIXED_IO */
- NULL, /* 0x0A, Reserved */
+ acpi_rs_convert_fixed_dma, /* 0x0A, ACPI_RESOURCE_NAME_FIXED_DMA */
NULL, /* 0x0B, Reserved */
NULL, /* 0x0C, Reserved */
NULL, /* 0x0D, Reserved */
@@ -114,7 +117,19 @@ struct acpi_rsconvert_info *acpi_gbl_get_resource_dispatch[] = {
acpi_rs_convert_address16, /* 0x08, ACPI_RESOURCE_NAME_ADDRESS16 */
acpi_rs_convert_ext_irq, /* 0x09, ACPI_RESOURCE_NAME_EXTENDED_IRQ */
acpi_rs_convert_address64, /* 0x0A, ACPI_RESOURCE_NAME_ADDRESS64 */
- acpi_rs_convert_ext_address64 /* 0x0B, ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64 */
+ acpi_rs_convert_ext_address64, /* 0x0B, ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64 */
+ acpi_rs_convert_gpio, /* 0x0C, ACPI_RESOURCE_NAME_GPIO */
+ NULL, /* 0x0D, Reserved */
+ NULL, /* 0x0E, ACPI_RESOURCE_NAME_SERIAL_BUS - Use subtype table below */
+};
+
+/* Subtype table for serial_bus -- I2C, SPI, and UART */
+
+struct acpi_rsconvert_info *acpi_gbl_convert_resource_serial_bus_dispatch[] = {
+ NULL,
+ acpi_rs_convert_i2c_serial_bus,
+ acpi_rs_convert_spi_serial_bus,
+ acpi_rs_convert_uart_serial_bus,
};
#ifdef ACPI_FUTURE_USAGE
@@ -140,6 +155,16 @@ struct acpi_rsdump_info *acpi_gbl_dump_resource_dispatch[] = {
acpi_rs_dump_ext_address64, /* ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64 */
acpi_rs_dump_ext_irq, /* ACPI_RESOURCE_TYPE_EXTENDED_IRQ */
acpi_rs_dump_generic_reg, /* ACPI_RESOURCE_TYPE_GENERIC_REGISTER */
+ acpi_rs_dump_gpio, /* ACPI_RESOURCE_TYPE_GPIO */
+ acpi_rs_dump_fixed_dma, /* ACPI_RESOURCE_TYPE_FIXED_DMA */
+ NULL, /* ACPI_RESOURCE_TYPE_SERIAL_BUS */
+};
+
+struct acpi_rsdump_info *acpi_gbl_dump_serial_bus_dispatch[] = {
+ NULL,
+ acpi_rs_dump_i2c_serial_bus, /* AML_RESOURCE_I2C_BUS_TYPE */
+ acpi_rs_dump_spi_serial_bus, /* AML_RESOURCE_SPI_BUS_TYPE */
+ acpi_rs_dump_uart_serial_bus, /* AML_RESOURCE_UART_BUS_TYPE */
};
#endif
@@ -166,7 +191,10 @@ const u8 acpi_gbl_aml_resource_sizes[] = {
sizeof(struct aml_resource_address64), /* ACPI_RESOURCE_TYPE_ADDRESS64 */
sizeof(struct aml_resource_extended_address64), /*ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64 */
sizeof(struct aml_resource_extended_irq), /* ACPI_RESOURCE_TYPE_EXTENDED_IRQ */
- sizeof(struct aml_resource_generic_register) /* ACPI_RESOURCE_TYPE_GENERIC_REGISTER */
+ sizeof(struct aml_resource_generic_register), /* ACPI_RESOURCE_TYPE_GENERIC_REGISTER */
+ sizeof(struct aml_resource_gpio), /* ACPI_RESOURCE_TYPE_GPIO */
+ sizeof(struct aml_resource_fixed_dma), /* ACPI_RESOURCE_TYPE_FIXED_DMA */
+ sizeof(struct aml_resource_common_serialbus), /* ACPI_RESOURCE_TYPE_SERIAL_BUS */
};
const u8 acpi_gbl_resource_struct_sizes[] = {
@@ -182,7 +210,7 @@ const u8 acpi_gbl_resource_struct_sizes[] = {
ACPI_RS_SIZE_MIN,
ACPI_RS_SIZE(struct acpi_resource_io),
ACPI_RS_SIZE(struct acpi_resource_fixed_io),
- 0,
+ ACPI_RS_SIZE(struct acpi_resource_fixed_dma),
0,
0,
0,
@@ -202,5 +230,21 @@ const u8 acpi_gbl_resource_struct_sizes[] = {
ACPI_RS_SIZE(struct acpi_resource_address16),
ACPI_RS_SIZE(struct acpi_resource_extended_irq),
ACPI_RS_SIZE(struct acpi_resource_address64),
- ACPI_RS_SIZE(struct acpi_resource_extended_address64)
+ ACPI_RS_SIZE(struct acpi_resource_extended_address64),
+ ACPI_RS_SIZE(struct acpi_resource_gpio),
+ ACPI_RS_SIZE(struct acpi_resource_common_serialbus)
+};
+
+const u8 acpi_gbl_aml_resource_serial_bus_sizes[] = {
+ 0,
+ sizeof(struct aml_resource_i2c_serialbus),
+ sizeof(struct aml_resource_spi_serialbus),
+ sizeof(struct aml_resource_uart_serialbus),
+};
+
+const u8 acpi_gbl_resource_struct_serial_bus_sizes[] = {
+ 0,
+ ACPI_RS_SIZE(struct acpi_resource_i2c_serialbus),
+ ACPI_RS_SIZE(struct acpi_resource_spi_serialbus),
+ ACPI_RS_SIZE(struct acpi_resource_uart_serialbus),
};
diff --git a/drivers/acpi/acpica/rsio.c b/drivers/acpi/acpica/rsio.c
index 0c7efef008be..f6a081057a22 100644
--- a/drivers/acpi/acpica/rsio.c
+++ b/drivers/acpi/acpica/rsio.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/rsirq.c b/drivers/acpi/acpica/rsirq.c
index 50b8ad211167..e23a9ec248cb 100644
--- a/drivers/acpi/acpica/rsirq.c
+++ b/drivers/acpi/acpica/rsirq.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -264,3 +264,34 @@ struct acpi_rsconvert_info acpi_rs_convert_dma[6] = {
AML_OFFSET(dma.dma_channel_mask),
ACPI_RS_OFFSET(data.dma.channel_count)}
};
+
+/*******************************************************************************
+ *
+ * acpi_rs_convert_fixed_dma
+ *
+ ******************************************************************************/
+
+struct acpi_rsconvert_info acpi_rs_convert_fixed_dma[4] = {
+ {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_FIXED_DMA,
+ ACPI_RS_SIZE(struct acpi_resource_fixed_dma),
+ ACPI_RSC_TABLE_SIZE(acpi_rs_convert_fixed_dma)},
+
+ {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_FIXED_DMA,
+ sizeof(struct aml_resource_fixed_dma),
+ 0},
+
+ /*
+ * These fields are contiguous in both the source and destination:
+ * request_lines
+ * Channels
+ */
+
+ {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.fixed_dma.request_lines),
+ AML_OFFSET(fixed_dma.request_lines),
+ 2},
+
+ {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.fixed_dma.width),
+ AML_OFFSET(fixed_dma.width),
+ 1},
+
+};
diff --git a/drivers/acpi/acpica/rslist.c b/drivers/acpi/acpica/rslist.c
index 1bfcef736c50..9be129f5d6f4 100644
--- a/drivers/acpi/acpica/rslist.c
+++ b/drivers/acpi/acpica/rslist.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -70,6 +70,8 @@ acpi_rs_convert_aml_to_resources(u8 * aml,
struct acpi_resource **resource_ptr =
ACPI_CAST_INDIRECT_PTR(struct acpi_resource, context);
struct acpi_resource *resource;
+ union aml_resource *aml_resource;
+ struct acpi_rsconvert_info *conversion_table;
acpi_status status;
ACPI_FUNCTION_TRACE(rs_convert_aml_to_resources);
@@ -84,14 +86,37 @@ acpi_rs_convert_aml_to_resources(u8 * aml,
"Misaligned resource pointer %p", resource));
}
+ /* Get the appropriate conversion info table */
+
+ aml_resource = ACPI_CAST_PTR(union aml_resource, aml);
+ if (acpi_ut_get_resource_type(aml) == ACPI_RESOURCE_NAME_SERIAL_BUS) {
+ if (aml_resource->common_serial_bus.type >
+ AML_RESOURCE_MAX_SERIALBUSTYPE) {
+ conversion_table = NULL;
+ } else {
+ /* This is an I2C, SPI, or UART serial_bus descriptor */
+
+ conversion_table =
+ acpi_gbl_convert_resource_serial_bus_dispatch
+ [aml_resource->common_serial_bus.type];
+ }
+ } else {
+ conversion_table =
+ acpi_gbl_get_resource_dispatch[resource_index];
+ }
+
+ if (!conversion_table) {
+ ACPI_ERROR((AE_INFO,
+ "Invalid/unsupported resource descriptor: Type 0x%2.2X",
+ resource_index));
+ return (AE_AML_INVALID_RESOURCE_TYPE);
+ }
+
/* Convert the AML byte stream resource to a local resource struct */
status =
- acpi_rs_convert_aml_to_resource(resource,
- ACPI_CAST_PTR(union aml_resource,
- aml),
- acpi_gbl_get_resource_dispatch
- [resource_index]);
+ acpi_rs_convert_aml_to_resource(resource, aml_resource,
+ conversion_table);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Could not convert AML resource (Type 0x%X)",
@@ -106,7 +131,7 @@ acpi_rs_convert_aml_to_resources(u8 * aml,
/* Point to the next structure in the output buffer */
- *resource_ptr = ACPI_ADD_PTR(void, resource, resource->length);
+ *resource_ptr = ACPI_NEXT_RESOURCE(resource);
return_ACPI_STATUS(AE_OK);
}
@@ -135,6 +160,7 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource,
{
u8 *aml = output_buffer;
u8 *end_aml = output_buffer + aml_size_needed;
+ struct acpi_rsconvert_info *conversion_table;
acpi_status status;
ACPI_FUNCTION_TRACE(rs_convert_resources_to_aml);
@@ -154,11 +180,34 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource,
/* Perform the conversion */
- status = acpi_rs_convert_resource_to_aml(resource, ACPI_CAST_PTR(union
- aml_resource,
- aml),
- acpi_gbl_set_resource_dispatch
- [resource->type]);
+ if (resource->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
+ if (resource->data.common_serial_bus.type >
+ AML_RESOURCE_MAX_SERIALBUSTYPE) {
+ conversion_table = NULL;
+ } else {
+ /* This is an I2C, SPI, or UART serial_bus descriptor */
+
+ conversion_table =
+ acpi_gbl_convert_resource_serial_bus_dispatch
+ [resource->data.common_serial_bus.type];
+ }
+ } else {
+ conversion_table =
+ acpi_gbl_set_resource_dispatch[resource->type];
+ }
+
+ if (!conversion_table) {
+ ACPI_ERROR((AE_INFO,
+ "Invalid/unsupported resource descriptor: Type 0x%2.2X",
+ resource->type));
+ return (AE_AML_INVALID_RESOURCE_TYPE);
+ }
+
+ status = acpi_rs_convert_resource_to_aml(resource,
+ ACPI_CAST_PTR(union
+ aml_resource,
+ aml),
+ conversion_table);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Could not convert resource (type 0x%X) to AML",
@@ -192,9 +241,7 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource,
/* Point to the next input resource descriptor */
- resource =
- ACPI_ADD_PTR(struct acpi_resource, resource,
- resource->length);
+ resource = ACPI_NEXT_RESOURCE(resource);
}
/* Completed buffer, but did not find an end_tag resource descriptor */
diff --git a/drivers/acpi/acpica/rsmemory.c b/drivers/acpi/acpica/rsmemory.c
index 7cc6d8625f1e..4fd611ad02b4 100644
--- a/drivers/acpi/acpica/rsmemory.c
+++ b/drivers/acpi/acpica/rsmemory.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/rsmisc.c b/drivers/acpi/acpica/rsmisc.c
index 410264b22a29..8073b371cc7c 100644
--- a/drivers/acpi/acpica/rsmisc.c
+++ b/drivers/acpi/acpica/rsmisc.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -83,6 +83,10 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource,
ACPI_FUNCTION_TRACE(rs_convert_aml_to_resource);
+ if (!info) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
+ }
+
if (((acpi_size) resource) & 0x3) {
/* Each internal resource struct is expected to be 32-bit aligned */
@@ -101,7 +105,6 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource,
* table length (# of table entries)
*/
count = INIT_TABLE_LENGTH(info);
-
while (count) {
/*
* Source is the external AML byte stream buffer,
@@ -145,6 +148,14 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource,
((ACPI_GET8(source) >> info->value) & 0x03);
break;
+ case ACPI_RSC_3BITFLAG:
+ /*
+ * Mask and shift the flag bits
+ */
+ ACPI_SET8(destination) = (u8)
+ ((ACPI_GET8(source) >> info->value) & 0x07);
+ break;
+
case ACPI_RSC_COUNT:
item_count = ACPI_GET8(source);
@@ -163,6 +174,69 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource,
(info->value * (item_count - 1));
break;
+ case ACPI_RSC_COUNT_GPIO_PIN:
+
+ target = ACPI_ADD_PTR(void, aml, info->value);
+ item_count = ACPI_GET16(target) - ACPI_GET16(source);
+
+ resource->length = resource->length + item_count;
+ item_count = item_count / 2;
+ ACPI_SET16(destination) = item_count;
+ break;
+
+ case ACPI_RSC_COUNT_GPIO_VEN:
+
+ item_count = ACPI_GET8(source);
+ ACPI_SET8(destination) = (u8)item_count;
+
+ resource->length = resource->length +
+ (info->value * item_count);
+ break;
+
+ case ACPI_RSC_COUNT_GPIO_RES:
+
+ /*
+ * Vendor data is optional (length/offset may both be zero)
+ * Examine vendor data length field first
+ */
+ target = ACPI_ADD_PTR(void, aml, (info->value + 2));
+ if (ACPI_GET16(target)) {
+
+ /* Use vendor offset to get resource source length */
+
+ target = ACPI_ADD_PTR(void, aml, info->value);
+ item_count =
+ ACPI_GET16(target) - ACPI_GET16(source);
+ } else {
+ /* No vendor data to worry about */
+
+ item_count = aml->large_header.resource_length +
+ sizeof(struct aml_resource_large_header) -
+ ACPI_GET16(source);
+ }
+
+ resource->length = resource->length + item_count;
+ ACPI_SET16(destination) = item_count;
+ break;
+
+ case ACPI_RSC_COUNT_SERIAL_VEN:
+
+ item_count = ACPI_GET16(source) - info->value;
+
+ resource->length = resource->length + item_count;
+ ACPI_SET16(destination) = item_count;
+ break;
+
+ case ACPI_RSC_COUNT_SERIAL_RES:
+
+ item_count = (aml_resource_length +
+ sizeof(struct aml_resource_large_header))
+ - ACPI_GET16(source) - info->value;
+
+ resource->length = resource->length + item_count;
+ ACPI_SET16(destination) = item_count;
+ break;
+
case ACPI_RSC_LENGTH:
resource->length = resource->length + info->value;
@@ -183,6 +257,72 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource,
info->opcode);
break;
+ case ACPI_RSC_MOVE_GPIO_PIN:
+
+ /* Generate and set the PIN data pointer */
+
+ target = (char *)ACPI_ADD_PTR(void, resource,
+ (resource->length -
+ item_count * 2));
+ *(u16 **)destination = ACPI_CAST_PTR(u16, target);
+
+ /* Copy the PIN data */
+
+ source = ACPI_ADD_PTR(void, aml, ACPI_GET16(source));
+ acpi_rs_move_data(target, source, item_count,
+ info->opcode);
+ break;
+
+ case ACPI_RSC_MOVE_GPIO_RES:
+
+ /* Generate and set the resource_source string pointer */
+
+ target = (char *)ACPI_ADD_PTR(void, resource,
+ (resource->length -
+ item_count));
+ *(u8 **)destination = ACPI_CAST_PTR(u8, target);
+
+ /* Copy the resource_source string */
+
+ source = ACPI_ADD_PTR(void, aml, ACPI_GET16(source));
+ acpi_rs_move_data(target, source, item_count,
+ info->opcode);
+ break;
+
+ case ACPI_RSC_MOVE_SERIAL_VEN:
+
+ /* Generate and set the Vendor Data pointer */
+
+ target = (char *)ACPI_ADD_PTR(void, resource,
+ (resource->length -
+ item_count));
+ *(u8 **)destination = ACPI_CAST_PTR(u8, target);
+
+ /* Copy the Vendor Data */
+
+ source = ACPI_ADD_PTR(void, aml, info->value);
+ acpi_rs_move_data(target, source, item_count,
+ info->opcode);
+ break;
+
+ case ACPI_RSC_MOVE_SERIAL_RES:
+
+ /* Generate and set the resource_source string pointer */
+
+ target = (char *)ACPI_ADD_PTR(void, resource,
+ (resource->length -
+ item_count));
+ *(u8 **)destination = ACPI_CAST_PTR(u8, target);
+
+ /* Copy the resource_source string */
+
+ source =
+ ACPI_ADD_PTR(void, aml,
+ (ACPI_GET16(source) + info->value));
+ acpi_rs_move_data(target, source, item_count,
+ info->opcode);
+ break;
+
case ACPI_RSC_SET8:
ACPI_MEMSET(destination, info->aml_offset, info->value);
@@ -219,13 +359,18 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource,
* Optional resource_source (Index and String). This is the more
* complicated case used by the Interrupt() macro
*/
- target =
- ACPI_ADD_PTR(char, resource,
- info->aml_offset + (item_count * 4));
+ target = ACPI_ADD_PTR(char, resource,
+ info->aml_offset +
+ (item_count * 4));
resource->length +=
acpi_rs_get_resource_source(aml_resource_length,
- (acpi_rs_length) (((item_count - 1) * sizeof(u32)) + info->value), destination, aml, target);
+ (acpi_rs_length)
+ (((item_count -
+ 1) * sizeof(u32)) +
+ info->value),
+ destination, aml,
+ target);
break;
case ACPI_RSC_BITMASK:
@@ -327,6 +472,7 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource,
{
void *source = NULL;
void *destination;
+ char *target;
acpi_rsdesc_size aml_length = 0;
u8 count;
u16 temp16 = 0;
@@ -334,6 +480,10 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource,
ACPI_FUNCTION_TRACE(rs_convert_resource_to_aml);
+ if (!info) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
+ }
+
/*
* First table entry must be ACPI_RSC_INITxxx and must contain the
* table length (# of table entries)
@@ -383,6 +533,14 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource,
((ACPI_GET8(source) & 0x03) << info->value);
break;
+ case ACPI_RSC_3BITFLAG:
+ /*
+ * Mask and shift the flag bits
+ */
+ ACPI_SET8(destination) |= (u8)
+ ((ACPI_GET8(source) & 0x07) << info->value);
+ break;
+
case ACPI_RSC_COUNT:
item_count = ACPI_GET8(source);
@@ -400,6 +558,63 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource,
acpi_rs_set_resource_length(aml_length, aml);
break;
+ case ACPI_RSC_COUNT_GPIO_PIN:
+
+ item_count = ACPI_GET16(source);
+ ACPI_SET16(destination) = (u16)aml_length;
+
+ aml_length = (u16)(aml_length + item_count * 2);
+ target = ACPI_ADD_PTR(void, aml, info->value);
+ ACPI_SET16(target) = (u16)aml_length;
+ acpi_rs_set_resource_length(aml_length, aml);
+ break;
+
+ case ACPI_RSC_COUNT_GPIO_VEN:
+
+ item_count = ACPI_GET16(source);
+ ACPI_SET16(destination) = (u16)item_count;
+
+ aml_length =
+ (u16)(aml_length + (info->value * item_count));
+ acpi_rs_set_resource_length(aml_length, aml);
+ break;
+
+ case ACPI_RSC_COUNT_GPIO_RES:
+
+ /* Set resource source string length */
+
+ item_count = ACPI_GET16(source);
+ ACPI_SET16(destination) = (u16)aml_length;
+
+ /* Compute offset for the Vendor Data */
+
+ aml_length = (u16)(aml_length + item_count);
+ target = ACPI_ADD_PTR(void, aml, info->value);
+
+ /* Set vendor offset only if there is vendor data */
+
+ if (resource->data.gpio.vendor_length) {
+ ACPI_SET16(target) = (u16)aml_length;
+ }
+
+ acpi_rs_set_resource_length(aml_length, aml);
+ break;
+
+ case ACPI_RSC_COUNT_SERIAL_VEN:
+
+ item_count = ACPI_GET16(source);
+ ACPI_SET16(destination) = item_count + info->value;
+ aml_length = (u16)(aml_length + item_count);
+ acpi_rs_set_resource_length(aml_length, aml);
+ break;
+
+ case ACPI_RSC_COUNT_SERIAL_RES:
+
+ item_count = ACPI_GET16(source);
+ aml_length = (u16)(aml_length + item_count);
+ acpi_rs_set_resource_length(aml_length, aml);
+ break;
+
case ACPI_RSC_LENGTH:
acpi_rs_set_resource_length(info->value, aml);
@@ -417,6 +632,48 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource,
info->opcode);
break;
+ case ACPI_RSC_MOVE_GPIO_PIN:
+
+ destination = (char *)ACPI_ADD_PTR(void, aml,
+ ACPI_GET16
+ (destination));
+ source = *(u16 **)source;
+ acpi_rs_move_data(destination, source, item_count,
+ info->opcode);
+ break;
+
+ case ACPI_RSC_MOVE_GPIO_RES:
+
+ /* Used for both resource_source string and vendor_data */
+
+ destination = (char *)ACPI_ADD_PTR(void, aml,
+ ACPI_GET16
+ (destination));
+ source = *(u8 **)source;
+ acpi_rs_move_data(destination, source, item_count,
+ info->opcode);
+ break;
+
+ case ACPI_RSC_MOVE_SERIAL_VEN:
+
+ destination = (char *)ACPI_ADD_PTR(void, aml,
+ (aml_length -
+ item_count));
+ source = *(u8 **)source;
+ acpi_rs_move_data(destination, source, item_count,
+ info->opcode);
+ break;
+
+ case ACPI_RSC_MOVE_SERIAL_RES:
+
+ destination = (char *)ACPI_ADD_PTR(void, aml,
+ (aml_length -
+ item_count));
+ source = *(u8 **)source;
+ acpi_rs_move_data(destination, source, item_count,
+ info->opcode);
+ break;
+
case ACPI_RSC_ADDRESS:
/* Set the Resource Type, General Flags, and Type-Specific Flags */
diff --git a/drivers/acpi/acpica/rsserial.c b/drivers/acpi/acpica/rsserial.c
new file mode 100644
index 000000000000..9aa5e689b444
--- /dev/null
+++ b/drivers/acpi/acpica/rsserial.c
@@ -0,0 +1,441 @@
+/*******************************************************************************
+ *
+ * Module Name: rsserial - GPIO/serial_bus resource descriptors
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2012, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "acresrc.h"
+
+#define _COMPONENT ACPI_RESOURCES
+ACPI_MODULE_NAME("rsserial")
+
+/*******************************************************************************
+ *
+ * acpi_rs_convert_gpio
+ *
+ ******************************************************************************/
+struct acpi_rsconvert_info acpi_rs_convert_gpio[17] = {
+ {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_GPIO,
+ ACPI_RS_SIZE(struct acpi_resource_gpio),
+ ACPI_RSC_TABLE_SIZE(acpi_rs_convert_gpio)},
+
+ {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_GPIO,
+ sizeof(struct aml_resource_gpio),
+ 0},
+
+ /*
+ * These fields are contiguous in both the source and destination:
+ * revision_id
+ * connection_type
+ */
+ {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.gpio.revision_id),
+ AML_OFFSET(gpio.revision_id),
+ 2},
+
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.gpio.producer_consumer),
+ AML_OFFSET(gpio.flags),
+ 0},
+
+ {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.gpio.sharable),
+ AML_OFFSET(gpio.int_flags),
+ 3},
+
+ {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.gpio.io_restriction),
+ AML_OFFSET(gpio.int_flags),
+ 0},
+
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.gpio.triggering),
+ AML_OFFSET(gpio.int_flags),
+ 0},
+
+ {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.gpio.polarity),
+ AML_OFFSET(gpio.int_flags),
+ 1},
+
+ {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.gpio.pin_config),
+ AML_OFFSET(gpio.pin_config),
+ 1},
+
+ /*
+ * These fields are contiguous in both the source and destination:
+ * drive_strength
+ * debounce_timeout
+ */
+ {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.gpio.drive_strength),
+ AML_OFFSET(gpio.drive_strength),
+ 2},
+
+ /* Pin Table */
+
+ {ACPI_RSC_COUNT_GPIO_PIN, ACPI_RS_OFFSET(data.gpio.pin_table_length),
+ AML_OFFSET(gpio.pin_table_offset),
+ AML_OFFSET(gpio.res_source_offset)},
+
+ {ACPI_RSC_MOVE_GPIO_PIN, ACPI_RS_OFFSET(data.gpio.pin_table),
+ AML_OFFSET(gpio.pin_table_offset),
+ 0},
+
+ /* Resource Source */
+
+ {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.gpio.resource_source.index),
+ AML_OFFSET(gpio.res_source_index),
+ 1},
+
+ {ACPI_RSC_COUNT_GPIO_RES,
+ ACPI_RS_OFFSET(data.gpio.resource_source.string_length),
+ AML_OFFSET(gpio.res_source_offset),
+ AML_OFFSET(gpio.vendor_offset)},
+
+ {ACPI_RSC_MOVE_GPIO_RES,
+ ACPI_RS_OFFSET(data.gpio.resource_source.string_ptr),
+ AML_OFFSET(gpio.res_source_offset),
+ 0},
+
+ /* Vendor Data */
+
+ {ACPI_RSC_COUNT_GPIO_VEN, ACPI_RS_OFFSET(data.gpio.vendor_length),
+ AML_OFFSET(gpio.vendor_length),
+ 1},
+
+ {ACPI_RSC_MOVE_GPIO_RES, ACPI_RS_OFFSET(data.gpio.vendor_data),
+ AML_OFFSET(gpio.vendor_offset),
+ 0},
+};
+
+/*******************************************************************************
+ *
+ * acpi_rs_convert_i2c_serial_bus
+ *
+ ******************************************************************************/
+
+struct acpi_rsconvert_info acpi_rs_convert_i2c_serial_bus[16] = {
+ {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_SERIAL_BUS,
+ ACPI_RS_SIZE(struct acpi_resource_i2c_serialbus),
+ ACPI_RSC_TABLE_SIZE(acpi_rs_convert_i2c_serial_bus)},
+
+ {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_SERIAL_BUS,
+ sizeof(struct aml_resource_i2c_serialbus),
+ 0},
+
+ {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.common_serial_bus.revision_id),
+ AML_OFFSET(common_serial_bus.revision_id),
+ 1},
+
+ {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.common_serial_bus.type),
+ AML_OFFSET(common_serial_bus.type),
+ 1},
+
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.common_serial_bus.slave_mode),
+ AML_OFFSET(common_serial_bus.flags),
+ 0},
+
+ {ACPI_RSC_1BITFLAG,
+ ACPI_RS_OFFSET(data.common_serial_bus.producer_consumer),
+ AML_OFFSET(common_serial_bus.flags),
+ 1},
+
+ {ACPI_RSC_MOVE8,
+ ACPI_RS_OFFSET(data.common_serial_bus.type_revision_id),
+ AML_OFFSET(common_serial_bus.type_revision_id),
+ 1},
+
+ {ACPI_RSC_MOVE16,
+ ACPI_RS_OFFSET(data.common_serial_bus.type_data_length),
+ AML_OFFSET(common_serial_bus.type_data_length),
+ 1},
+
+ /* Vendor data */
+
+ {ACPI_RSC_COUNT_SERIAL_VEN,
+ ACPI_RS_OFFSET(data.common_serial_bus.vendor_length),
+ AML_OFFSET(common_serial_bus.type_data_length),
+ AML_RESOURCE_I2C_MIN_DATA_LEN},
+
+ {ACPI_RSC_MOVE_SERIAL_VEN,
+ ACPI_RS_OFFSET(data.common_serial_bus.vendor_data),
+ 0,
+ sizeof(struct aml_resource_i2c_serialbus)},
+
+ /* Resource Source */
+
+ {ACPI_RSC_MOVE8,
+ ACPI_RS_OFFSET(data.common_serial_bus.resource_source.index),
+ AML_OFFSET(common_serial_bus.res_source_index),
+ 1},
+
+ {ACPI_RSC_COUNT_SERIAL_RES,
+ ACPI_RS_OFFSET(data.common_serial_bus.resource_source.string_length),
+ AML_OFFSET(common_serial_bus.type_data_length),
+ sizeof(struct aml_resource_common_serialbus)},
+
+ {ACPI_RSC_MOVE_SERIAL_RES,
+ ACPI_RS_OFFSET(data.common_serial_bus.resource_source.string_ptr),
+ AML_OFFSET(common_serial_bus.type_data_length),
+ sizeof(struct aml_resource_common_serialbus)},
+
+ /* I2C bus type specific */
+
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.i2c_serial_bus.access_mode),
+ AML_OFFSET(i2c_serial_bus.type_specific_flags),
+ 0},
+
+ {ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.i2c_serial_bus.connection_speed),
+ AML_OFFSET(i2c_serial_bus.connection_speed),
+ 1},
+
+ {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.i2c_serial_bus.slave_address),
+ AML_OFFSET(i2c_serial_bus.slave_address),
+ 1},
+};
+
+/*******************************************************************************
+ *
+ * acpi_rs_convert_spi_serial_bus
+ *
+ ******************************************************************************/
+
+struct acpi_rsconvert_info acpi_rs_convert_spi_serial_bus[20] = {
+ {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_SERIAL_BUS,
+ ACPI_RS_SIZE(struct acpi_resource_spi_serialbus),
+ ACPI_RSC_TABLE_SIZE(acpi_rs_convert_spi_serial_bus)},
+
+ {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_SERIAL_BUS,
+ sizeof(struct aml_resource_spi_serialbus),
+ 0},
+
+ {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.common_serial_bus.revision_id),
+ AML_OFFSET(common_serial_bus.revision_id),
+ 1},
+
+ {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.common_serial_bus.type),
+ AML_OFFSET(common_serial_bus.type),
+ 1},
+
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.common_serial_bus.slave_mode),
+ AML_OFFSET(common_serial_bus.flags),
+ 0},
+
+ {ACPI_RSC_1BITFLAG,
+ ACPI_RS_OFFSET(data.common_serial_bus.producer_consumer),
+ AML_OFFSET(common_serial_bus.flags),
+ 1},
+
+ {ACPI_RSC_MOVE8,
+ ACPI_RS_OFFSET(data.common_serial_bus.type_revision_id),
+ AML_OFFSET(common_serial_bus.type_revision_id),
+ 1},
+
+ {ACPI_RSC_MOVE16,
+ ACPI_RS_OFFSET(data.common_serial_bus.type_data_length),
+ AML_OFFSET(common_serial_bus.type_data_length),
+ 1},
+
+ /* Vendor data */
+
+ {ACPI_RSC_COUNT_SERIAL_VEN,
+ ACPI_RS_OFFSET(data.common_serial_bus.vendor_length),
+ AML_OFFSET(common_serial_bus.type_data_length),
+ AML_RESOURCE_SPI_MIN_DATA_LEN},
+
+ {ACPI_RSC_MOVE_SERIAL_VEN,
+ ACPI_RS_OFFSET(data.common_serial_bus.vendor_data),
+ 0,
+ sizeof(struct aml_resource_spi_serialbus)},
+
+ /* Resource Source */
+
+ {ACPI_RSC_MOVE8,
+ ACPI_RS_OFFSET(data.common_serial_bus.resource_source.index),
+ AML_OFFSET(common_serial_bus.res_source_index),
+ 1},
+
+ {ACPI_RSC_COUNT_SERIAL_RES,
+ ACPI_RS_OFFSET(data.common_serial_bus.resource_source.string_length),
+ AML_OFFSET(common_serial_bus.type_data_length),
+ sizeof(struct aml_resource_common_serialbus)},
+
+ {ACPI_RSC_MOVE_SERIAL_RES,
+ ACPI_RS_OFFSET(data.common_serial_bus.resource_source.string_ptr),
+ AML_OFFSET(common_serial_bus.type_data_length),
+ sizeof(struct aml_resource_common_serialbus)},
+
+ /* Spi bus type specific */
+
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.spi_serial_bus.wire_mode),
+ AML_OFFSET(spi_serial_bus.type_specific_flags),
+ 0},
+
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.spi_serial_bus.device_polarity),
+ AML_OFFSET(spi_serial_bus.type_specific_flags),
+ 1},
+
+ {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.spi_serial_bus.data_bit_length),
+ AML_OFFSET(spi_serial_bus.data_bit_length),
+ 1},
+
+ {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.spi_serial_bus.clock_phase),
+ AML_OFFSET(spi_serial_bus.clock_phase),
+ 1},
+
+ {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.spi_serial_bus.clock_polarity),
+ AML_OFFSET(spi_serial_bus.clock_polarity),
+ 1},
+
+ {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.spi_serial_bus.device_selection),
+ AML_OFFSET(spi_serial_bus.device_selection),
+ 1},
+
+ {ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.spi_serial_bus.connection_speed),
+ AML_OFFSET(spi_serial_bus.connection_speed),
+ 1},
+};
+
+/*******************************************************************************
+ *
+ * acpi_rs_convert_uart_serial_bus
+ *
+ ******************************************************************************/
+
+struct acpi_rsconvert_info acpi_rs_convert_uart_serial_bus[22] = {
+ {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_SERIAL_BUS,
+ ACPI_RS_SIZE(struct acpi_resource_uart_serialbus),
+ ACPI_RSC_TABLE_SIZE(acpi_rs_convert_uart_serial_bus)},
+
+ {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_SERIAL_BUS,
+ sizeof(struct aml_resource_uart_serialbus),
+ 0},
+
+ {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.common_serial_bus.revision_id),
+ AML_OFFSET(common_serial_bus.revision_id),
+ 1},
+
+ {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.common_serial_bus.type),
+ AML_OFFSET(common_serial_bus.type),
+ 1},
+
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.common_serial_bus.slave_mode),
+ AML_OFFSET(common_serial_bus.flags),
+ 0},
+
+ {ACPI_RSC_1BITFLAG,
+ ACPI_RS_OFFSET(data.common_serial_bus.producer_consumer),
+ AML_OFFSET(common_serial_bus.flags),
+ 1},
+
+ {ACPI_RSC_MOVE8,
+ ACPI_RS_OFFSET(data.common_serial_bus.type_revision_id),
+ AML_OFFSET(common_serial_bus.type_revision_id),
+ 1},
+
+ {ACPI_RSC_MOVE16,
+ ACPI_RS_OFFSET(data.common_serial_bus.type_data_length),
+ AML_OFFSET(common_serial_bus.type_data_length),
+ 1},
+
+ /* Vendor data */
+
+ {ACPI_RSC_COUNT_SERIAL_VEN,
+ ACPI_RS_OFFSET(data.common_serial_bus.vendor_length),
+ AML_OFFSET(common_serial_bus.type_data_length),
+ AML_RESOURCE_UART_MIN_DATA_LEN},
+
+ {ACPI_RSC_MOVE_SERIAL_VEN,
+ ACPI_RS_OFFSET(data.common_serial_bus.vendor_data),
+ 0,
+ sizeof(struct aml_resource_uart_serialbus)},
+
+ /* Resource Source */
+
+ {ACPI_RSC_MOVE8,
+ ACPI_RS_OFFSET(data.common_serial_bus.resource_source.index),
+ AML_OFFSET(common_serial_bus.res_source_index),
+ 1},
+
+ {ACPI_RSC_COUNT_SERIAL_RES,
+ ACPI_RS_OFFSET(data.common_serial_bus.resource_source.string_length),
+ AML_OFFSET(common_serial_bus.type_data_length),
+ sizeof(struct aml_resource_common_serialbus)},
+
+ {ACPI_RSC_MOVE_SERIAL_RES,
+ ACPI_RS_OFFSET(data.common_serial_bus.resource_source.string_ptr),
+ AML_OFFSET(common_serial_bus.type_data_length),
+ sizeof(struct aml_resource_common_serialbus)},
+
+ /* Uart bus type specific */
+
+ {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.uart_serial_bus.flow_control),
+ AML_OFFSET(uart_serial_bus.type_specific_flags),
+ 0},
+
+ {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.uart_serial_bus.stop_bits),
+ AML_OFFSET(uart_serial_bus.type_specific_flags),
+ 2},
+
+ {ACPI_RSC_3BITFLAG, ACPI_RS_OFFSET(data.uart_serial_bus.data_bits),
+ AML_OFFSET(uart_serial_bus.type_specific_flags),
+ 4},
+
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.uart_serial_bus.endian),
+ AML_OFFSET(uart_serial_bus.type_specific_flags),
+ 7},
+
+ {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.uart_serial_bus.parity),
+ AML_OFFSET(uart_serial_bus.parity),
+ 1},
+
+ {ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.uart_serial_bus.lines_enabled),
+ AML_OFFSET(uart_serial_bus.lines_enabled),
+ 1},
+
+ {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.uart_serial_bus.rx_fifo_size),
+ AML_OFFSET(uart_serial_bus.rx_fifo_size),
+ 1},
+
+ {ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.uart_serial_bus.tx_fifo_size),
+ AML_OFFSET(uart_serial_bus.tx_fifo_size),
+ 1},
+
+ {ACPI_RSC_MOVE32,
+ ACPI_RS_OFFSET(data.uart_serial_bus.default_baud_rate),
+ AML_OFFSET(uart_serial_bus.default_baud_rate),
+ 1},
+};
diff --git a/drivers/acpi/acpica/rsutils.c b/drivers/acpi/acpica/rsutils.c
index 231811e56939..433a375deb93 100644
--- a/drivers/acpi/acpica/rsutils.c
+++ b/drivers/acpi/acpica/rsutils.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -144,6 +144,9 @@ acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type)
* since there are no alignment or endian issues
*/
case ACPI_RSC_MOVE8:
+ case ACPI_RSC_MOVE_GPIO_RES:
+ case ACPI_RSC_MOVE_SERIAL_VEN:
+ case ACPI_RSC_MOVE_SERIAL_RES:
ACPI_MEMCPY(destination, source, item_count);
return;
@@ -153,6 +156,7 @@ acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type)
* misaligned memory transfers
*/
case ACPI_RSC_MOVE16:
+ case ACPI_RSC_MOVE_GPIO_PIN:
ACPI_MOVE_16_TO_16(&ACPI_CAST_PTR(u16, destination)[i],
&ACPI_CAST_PTR(u16, source)[i]);
break;
@@ -590,6 +594,56 @@ acpi_rs_get_prs_method_data(struct acpi_namespace_node *node,
/*******************************************************************************
*
+ * FUNCTION: acpi_rs_get_aei_method_data
+ *
+ * PARAMETERS: Node - Device node
+ * ret_buffer - Pointer to a buffer structure for the
+ * results
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: This function is called to get the _AEI value of an object
+ * contained in an object specified by the handle passed in
+ *
+ * If the function fails an appropriate status will be returned
+ * and the contents of the callers buffer is undefined.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_rs_get_aei_method_data(struct acpi_namespace_node *node,
+ struct acpi_buffer *ret_buffer)
+{
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE(rs_get_aei_method_data);
+
+ /* Parameters guaranteed valid by caller */
+
+ /* Execute the method, no parameters */
+
+ status = acpi_ut_evaluate_object(node, METHOD_NAME__AEI,
+ ACPI_BTYPE_BUFFER, &obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ /*
+ * Make the call to create a resource linked list from the
+ * byte stream buffer that comes back from the _CRS method
+ * execution.
+ */
+ status = acpi_rs_create_resource_list(obj_desc, ret_buffer);
+
+ /* On exit, we must delete the object returned by evaluate_object */
+
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_rs_get_method_data
*
* PARAMETERS: Handle - Handle to the containing object
diff --git a/drivers/acpi/acpica/rsxface.c b/drivers/acpi/acpica/rsxface.c
index fe86b37b16ce..f58c098c7aeb 100644
--- a/drivers/acpi/acpica/rsxface.c
+++ b/drivers/acpi/acpica/rsxface.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -307,6 +307,46 @@ acpi_set_current_resources(acpi_handle device_handle,
ACPI_EXPORT_SYMBOL(acpi_set_current_resources)
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_get_event_resources
+ *
+ * PARAMETERS: device_handle - Handle to the device object for the
+ * device we are getting resources
+ * in_buffer - Pointer to a buffer containing the
+ * resources to be set for the device
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: This function is called to get the event resources for a
+ * specific device. The caller must first acquire a handle for
+ * the desired device. The resource data is passed to the routine
+ * the buffer pointed to by the in_buffer variable. Uses the
+ * _AEI method.
+ *
+ ******************************************************************************/
+acpi_status
+acpi_get_event_resources(acpi_handle device_handle,
+ struct acpi_buffer *ret_buffer)
+{
+ acpi_status status;
+ struct acpi_namespace_node *node;
+
+ ACPI_FUNCTION_TRACE(acpi_get_event_resources);
+
+ /* Validate parameters then dispatch to internal routine */
+
+ status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ status = acpi_rs_get_aei_method_data(node, ret_buffer);
+ return_ACPI_STATUS(status);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_get_event_resources)
+
/******************************************************************************
*
* FUNCTION: acpi_resource_to_address64
@@ -486,8 +526,9 @@ acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context)
*
* PARAMETERS: device_handle - Handle to the device object for the
* device we are querying
- * Name - Method name of the resources we want
- * (METHOD_NAME__CRS or METHOD_NAME__PRS)
+ * Name - Method name of the resources we want.
+ * (METHOD_NAME__CRS, METHOD_NAME__PRS, or
+ * METHOD_NAME__AEI)
* user_function - Called for each resource
* Context - Passed to user_function
*
@@ -514,11 +555,12 @@ acpi_walk_resources(acpi_handle device_handle,
if (!device_handle || !user_function || !name ||
(!ACPI_COMPARE_NAME(name, METHOD_NAME__CRS) &&
- !ACPI_COMPARE_NAME(name, METHOD_NAME__PRS))) {
+ !ACPI_COMPARE_NAME(name, METHOD_NAME__PRS) &&
+ !ACPI_COMPARE_NAME(name, METHOD_NAME__AEI))) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- /* Get the _CRS or _PRS resource list */
+ /* Get the _CRS/_PRS/_AEI resource list */
buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
status = acpi_rs_get_method_data(device_handle, name, &buffer);
diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c
index 6f5588e62c0a..c5d870406f41 100644
--- a/drivers/acpi/acpica/tbfadt.c
+++ b/drivers/acpi/acpica/tbfadt.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -63,14 +63,15 @@ static void acpi_tb_setup_fadt_registers(void);
typedef struct acpi_fadt_info {
char *name;
- u8 address64;
- u8 address32;
- u8 length;
+ u16 address64;
+ u16 address32;
+ u16 length;
u8 default_length;
u8 type;
} acpi_fadt_info;
+#define ACPI_FADT_OPTIONAL 0
#define ACPI_FADT_REQUIRED 1
#define ACPI_FADT_SEPARATE_LENGTH 2
@@ -87,7 +88,7 @@ static struct acpi_fadt_info fadt_info_table[] = {
ACPI_FADT_OFFSET(pm1b_event_block),
ACPI_FADT_OFFSET(pm1_event_length),
ACPI_PM1_REGISTER_WIDTH * 2, /* Enable + Status register */
- 0},
+ ACPI_FADT_OPTIONAL},
{"Pm1aControlBlock",
ACPI_FADT_OFFSET(xpm1a_control_block),
@@ -101,7 +102,7 @@ static struct acpi_fadt_info fadt_info_table[] = {
ACPI_FADT_OFFSET(pm1b_control_block),
ACPI_FADT_OFFSET(pm1_control_length),
ACPI_PM1_REGISTER_WIDTH,
- 0},
+ ACPI_FADT_OPTIONAL},
{"Pm2ControlBlock",
ACPI_FADT_OFFSET(xpm2_control_block),
@@ -139,7 +140,7 @@ static struct acpi_fadt_info fadt_info_table[] = {
typedef struct acpi_fadt_pm_info {
struct acpi_generic_address *target;
- u8 source;
+ u16 source;
u8 register_num;
} acpi_fadt_pm_info;
@@ -253,8 +254,13 @@ void acpi_tb_parse_fadt(u32 table_index)
acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xdsdt,
ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT);
- acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xfacs,
- ACPI_SIG_FACS, ACPI_TABLE_INDEX_FACS);
+ /* If Hardware Reduced flag is set, there is no FACS */
+
+ if (!acpi_gbl_reduced_hardware) {
+ acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.
+ Xfacs, ACPI_SIG_FACS,
+ ACPI_TABLE_INDEX_FACS);
+ }
}
/*******************************************************************************
@@ -277,12 +283,12 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length)
{
/*
* Check if the FADT is larger than the largest table that we expect
- * (the ACPI 2.0/3.0 version). If so, truncate the table, and issue
+ * (the ACPI 5.0 version). If so, truncate the table, and issue
* a warning.
*/
if (length > sizeof(struct acpi_table_fadt)) {
ACPI_WARNING((AE_INFO,
- "FADT (revision %u) is longer than ACPI 2.0 version, "
+ "FADT (revision %u) is longer than ACPI 5.0 version, "
"truncating length %u to %u",
table->revision, length,
(u32)sizeof(struct acpi_table_fadt)));
@@ -297,6 +303,13 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length)
ACPI_MEMCPY(&acpi_gbl_FADT, table,
ACPI_MIN(length, sizeof(struct acpi_table_fadt)));
+ /* Take a copy of the Hardware Reduced flag */
+
+ acpi_gbl_reduced_hardware = FALSE;
+ if (acpi_gbl_FADT.flags & ACPI_FADT_HW_REDUCED) {
+ acpi_gbl_reduced_hardware = TRUE;
+ }
+
/* Convert the local copy of the FADT to the common internal format */
acpi_tb_convert_fadt();
@@ -502,6 +515,12 @@ static void acpi_tb_validate_fadt(void)
acpi_gbl_FADT.Xdsdt = (u64) acpi_gbl_FADT.dsdt;
}
+ /* If Hardware Reduced flag is set, we are all done */
+
+ if (acpi_gbl_reduced_hardware) {
+ return;
+ }
+
/* Examine all of the 64-bit extended address fields (X fields) */
for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) {
diff --git a/drivers/acpi/acpica/tbfind.c b/drivers/acpi/acpica/tbfind.c
index a55cb2bb5abb..4903e36ea75a 100644
--- a/drivers/acpi/acpica/tbfind.c
+++ b/drivers/acpi/acpica/tbfind.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c
index 62365f6075dd..1aecf7baa4e0 100644
--- a/drivers/acpi/acpica/tbinstal.c
+++ b/drivers/acpi/acpica/tbinstal.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c
index 0f2d395feaba..09ca39e14337 100644
--- a/drivers/acpi/acpica/tbutils.c
+++ b/drivers/acpi/acpica/tbutils.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -135,6 +135,13 @@ acpi_status acpi_tb_initialize_facs(void)
{
acpi_status status;
+ /* If Hardware Reduced flag is set, there is no FACS */
+
+ if (acpi_gbl_reduced_hardware) {
+ acpi_gbl_FACS = NULL;
+ return (AE_OK);
+ }
+
status = acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS,
ACPI_CAST_INDIRECT_PTR(struct
acpi_table_header,
diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c
index e7d13f5d3f2d..abcc6412c244 100644
--- a/drivers/acpi/acpica/tbxface.c
+++ b/drivers/acpi/acpica/tbxface.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/tbxfroot.c b/drivers/acpi/acpica/tbxfroot.c
index 7eb6c6cc1edf..4258f647ca3d 100644
--- a/drivers/acpi/acpica/tbxfroot.c
+++ b/drivers/acpi/acpica/tbxfroot.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utaddress.c b/drivers/acpi/acpica/utaddress.c
new file mode 100644
index 000000000000..67932aebe6dd
--- /dev/null
+++ b/drivers/acpi/acpica/utaddress.c
@@ -0,0 +1,294 @@
+/******************************************************************************
+ *
+ * Module Name: utaddress - op_region address range check
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2012, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "acnamesp.h"
+
+#define _COMPONENT ACPI_UTILITIES
+ACPI_MODULE_NAME("utaddress")
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_add_address_range
+ *
+ * PARAMETERS: space_id - Address space ID
+ * Address - op_region start address
+ * Length - op_region length
+ * region_node - op_region namespace node
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Add the Operation Region address range to the global list.
+ * The only supported Space IDs are Memory and I/O. Called when
+ * the op_region address/length operands are fully evaluated.
+ *
+ * MUTEX: Locks the namespace
+ *
+ * NOTE: Because this interface is only called when an op_region argument
+ * list is evaluated, there cannot be any duplicate region_nodes.
+ * Duplicate Address/Length values are allowed, however, so that multiple
+ * address conflicts can be detected.
+ *
+ ******************************************************************************/
+acpi_status
+acpi_ut_add_address_range(acpi_adr_space_type space_id,
+ acpi_physical_address address,
+ u32 length, struct acpi_namespace_node *region_node)
+{
+ struct acpi_address_range *range_info;
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE(ut_add_address_range);
+
+ if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
+ (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
+ return_ACPI_STATUS(AE_OK);
+ }
+
+ /* Allocate/init a new info block, add it to the appropriate list */
+
+ range_info = ACPI_ALLOCATE(sizeof(struct acpi_address_range));
+ if (!range_info) {
+ return_ACPI_STATUS(AE_NO_MEMORY);
+ }
+
+ range_info->start_address = address;
+ range_info->end_address = (address + length - 1);
+ range_info->region_node = region_node;
+
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ ACPI_FREE(range_info);
+ return_ACPI_STATUS(status);
+ }
+
+ range_info->next = acpi_gbl_address_range_list[space_id];
+ acpi_gbl_address_range_list[space_id] = range_info;
+
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "\nAdded [%4.4s] address range: 0x%p-0x%p\n",
+ acpi_ut_get_node_name(range_info->region_node),
+ ACPI_CAST_PTR(void, address),
+ ACPI_CAST_PTR(void, range_info->end_address)));
+
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS(AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_remove_address_range
+ *
+ * PARAMETERS: space_id - Address space ID
+ * region_node - op_region namespace node
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Remove the Operation Region from the global list. The only
+ * supported Space IDs are Memory and I/O. Called when an
+ * op_region is deleted.
+ *
+ * MUTEX: Assumes the namespace is locked
+ *
+ ******************************************************************************/
+
+void
+acpi_ut_remove_address_range(acpi_adr_space_type space_id,
+ struct acpi_namespace_node *region_node)
+{
+ struct acpi_address_range *range_info;
+ struct acpi_address_range *prev;
+
+ ACPI_FUNCTION_TRACE(ut_remove_address_range);
+
+ if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
+ (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
+ return_VOID;
+ }
+
+ /* Get the appropriate list head and check the list */
+
+ range_info = prev = acpi_gbl_address_range_list[space_id];
+ while (range_info) {
+ if (range_info->region_node == region_node) {
+ if (range_info == prev) { /* Found at list head */
+ acpi_gbl_address_range_list[space_id] =
+ range_info->next;
+ } else {
+ prev->next = range_info->next;
+ }
+
+ ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+ "\nRemoved [%4.4s] address range: 0x%p-0x%p\n",
+ acpi_ut_get_node_name(range_info->
+ region_node),
+ ACPI_CAST_PTR(void,
+ range_info->
+ start_address),
+ ACPI_CAST_PTR(void,
+ range_info->
+ end_address)));
+
+ ACPI_FREE(range_info);
+ return_VOID;
+ }
+
+ prev = range_info;
+ range_info = range_info->next;
+ }
+
+ return_VOID;
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_check_address_range
+ *
+ * PARAMETERS: space_id - Address space ID
+ * Address - Start address
+ * Length - Length of address range
+ * Warn - TRUE if warning on overlap desired
+ *
+ * RETURN: Count of the number of conflicts detected. Zero is always
+ * returned for Space IDs other than Memory or I/O.
+ *
+ * DESCRIPTION: Check if the input address range overlaps any of the
+ * ASL operation region address ranges. The only supported
+ * Space IDs are Memory and I/O.
+ *
+ * MUTEX: Assumes the namespace is locked.
+ *
+ ******************************************************************************/
+
+u32
+acpi_ut_check_address_range(acpi_adr_space_type space_id,
+ acpi_physical_address address, u32 length, u8 warn)
+{
+ struct acpi_address_range *range_info;
+ acpi_physical_address end_address;
+ char *pathname;
+ u32 overlap_count = 0;
+
+ ACPI_FUNCTION_TRACE(ut_check_address_range);
+
+ if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
+ (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
+ return_UINT32(0);
+ }
+
+ range_info = acpi_gbl_address_range_list[space_id];
+ end_address = address + length - 1;
+
+ /* Check entire list for all possible conflicts */
+
+ while (range_info) {
+ /*
+ * Check if the requested Address/Length overlaps this address_range.
+ * Four cases to consider:
+ *
+ * 1) Input address/length is contained completely in the address range
+ * 2) Input address/length overlaps range at the range start
+ * 3) Input address/length overlaps range at the range end
+ * 4) Input address/length completely encompasses the range
+ */
+ if ((address <= range_info->end_address) &&
+ (end_address >= range_info->start_address)) {
+
+ /* Found an address range overlap */
+
+ overlap_count++;
+ if (warn) { /* Optional warning message */
+ pathname =
+ acpi_ns_get_external_pathname(range_info->
+ region_node);
+
+ ACPI_WARNING((AE_INFO,
+ "0x%p-0x%p %s conflicts with Region %s %d",
+ ACPI_CAST_PTR(void, address),
+ ACPI_CAST_PTR(void, end_address),
+ acpi_ut_get_region_name(space_id),
+ pathname, overlap_count));
+ ACPI_FREE(pathname);
+ }
+ }
+
+ range_info = range_info->next;
+ }
+
+ return_UINT32(overlap_count);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_delete_address_lists
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Delete all global address range lists (called during
+ * subsystem shutdown).
+ *
+ ******************************************************************************/
+
+void acpi_ut_delete_address_lists(void)
+{
+ struct acpi_address_range *next;
+ struct acpi_address_range *range_info;
+ int i;
+
+ /* Delete all elements in all address range lists */
+
+ for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++) {
+ next = acpi_gbl_address_range_list[i];
+
+ while (next) {
+ range_info = next;
+ next = range_info->next;
+ ACPI_FREE(range_info);
+ }
+
+ acpi_gbl_address_range_list[i] = NULL;
+ }
+}
diff --git a/drivers/acpi/acpica/utalloc.c b/drivers/acpi/acpica/utalloc.c
index 0a697351cf69..9982d2ea66fb 100644
--- a/drivers/acpi/acpica/utalloc.c
+++ b/drivers/acpi/acpica/utalloc.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utcopy.c b/drivers/acpi/acpica/utcopy.c
index aded299a2fa8..3317c0a406ee 100644
--- a/drivers/acpi/acpica/utcopy.c
+++ b/drivers/acpi/acpica/utcopy.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c
index a1f8d7509e66..a0998a886318 100644
--- a/drivers/acpi/acpica/utdebug.c
+++ b/drivers/acpi/acpica/utdebug.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utdecode.c b/drivers/acpi/acpica/utdecode.c
index 8b087e2d64f4..d42ede5260c7 100644
--- a/drivers/acpi/acpica/utdecode.c
+++ b/drivers/acpi/acpica/utdecode.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -171,7 +171,9 @@ const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] = {
"SMBus",
"SystemCMOS",
"PCIBARTarget",
- "IPMI"
+ "IPMI",
+ "GeneralPurposeIo",
+ "GenericSerialBus"
};
char *acpi_ut_get_region_name(u8 space_id)
diff --git a/drivers/acpi/acpica/utdelete.c b/drivers/acpi/acpica/utdelete.c
index 31f5a7832ef1..2a6c3e183697 100644
--- a/drivers/acpi/acpica/utdelete.c
+++ b/drivers/acpi/acpica/utdelete.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -215,11 +215,14 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object)
ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
"***** Region %p\n", object));
- /* Invalidate the region address/length via the host OS */
-
- acpi_os_invalidate_address(object->region.space_id,
- object->region.address,
- (acpi_size) object->region.length);
+ /*
+ * Update address_range list. However, only permanent regions
+ * are installed in this list. (Not created within a method)
+ */
+ if (!(object->region.node->flags & ANOBJ_TEMPORARY)) {
+ acpi_ut_remove_address_range(object->region.space_id,
+ object->region.node);
+ }
second_desc = acpi_ns_get_secondary_object(object);
if (second_desc) {
diff --git a/drivers/acpi/acpica/uteval.c b/drivers/acpi/acpica/uteval.c
index 18f73c9d10bc..479f32b33415 100644
--- a/drivers/acpi/acpica/uteval.c
+++ b/drivers/acpi/acpica/uteval.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c
index ffba0a39c3e8..4153584cf526 100644
--- a/drivers/acpi/acpica/utglobal.c
+++ b/drivers/acpi/acpica/utglobal.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -264,6 +264,12 @@ acpi_status acpi_ut_init_globals(void)
return_ACPI_STATUS(status);
}
+ /* Address Range lists */
+
+ for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++) {
+ acpi_gbl_address_range_list[i] = NULL;
+ }
+
/* Mutex locked flags */
for (i = 0; i < ACPI_NUM_MUTEX; i++) {
diff --git a/drivers/acpi/acpica/utids.c b/drivers/acpi/acpica/utids.c
index b679ea693545..c92eb1d93785 100644
--- a/drivers/acpi/acpica/utids.c
+++ b/drivers/acpi/acpica/utids.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utinit.c b/drivers/acpi/acpica/utinit.c
index 191b6828cce9..8359c0c5dc98 100644
--- a/drivers/acpi/acpica/utinit.c
+++ b/drivers/acpi/acpica/utinit.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -92,6 +92,7 @@ static void acpi_ut_terminate(void)
gpe_xrupt_info = next_gpe_xrupt_info;
}
+ acpi_ut_delete_address_lists();
return_VOID;
}
diff --git a/drivers/acpi/acpica/utlock.c b/drivers/acpi/acpica/utlock.c
index f6bb75c6faf5..155fd786d0f2 100644
--- a/drivers/acpi/acpica/utlock.c
+++ b/drivers/acpi/acpica/utlock.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utmath.c b/drivers/acpi/acpica/utmath.c
index ce481da9bb45..2491a552b0e6 100644
--- a/drivers/acpi/acpica/utmath.c
+++ b/drivers/acpi/acpica/utmath.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utmisc.c b/drivers/acpi/acpica/utmisc.c
index c33a852d4f42..86f19db74e05 100644
--- a/drivers/acpi/acpica/utmisc.c
+++ b/drivers/acpi/acpica/utmisc.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utmutex.c b/drivers/acpi/acpica/utmutex.c
index 7d797e2baecd..43174df33121 100644
--- a/drivers/acpi/acpica/utmutex.c
+++ b/drivers/acpi/acpica/utmutex.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -293,14 +293,10 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id)
{
- acpi_thread_id this_thread_id;
-
ACPI_FUNCTION_NAME(ut_release_mutex);
- this_thread_id = acpi_os_get_thread_id();
-
ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Thread %u releasing Mutex [%s]\n",
- (u32)this_thread_id,
+ (u32)acpi_os_get_thread_id(),
acpi_ut_get_mutex_name(mutex_id)));
if (mutex_id > ACPI_MAX_MUTEX) {
@@ -329,7 +325,8 @@ acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id)
* the ACPI subsystem code.
*/
for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) {
- if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) {
+ if (acpi_gbl_mutex_info[i].thread_id ==
+ acpi_os_get_thread_id()) {
if (i == mutex_id) {
continue;
}
diff --git a/drivers/acpi/acpica/utobject.c b/drivers/acpi/acpica/utobject.c
index 188340a017b4..b112744fc9ae 100644
--- a/drivers/acpi/acpica/utobject.c
+++ b/drivers/acpi/acpica/utobject.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utosi.c b/drivers/acpi/acpica/utosi.c
index 1fb10cb8f11d..2360cf70c18c 100644
--- a/drivers/acpi/acpica/utosi.c
+++ b/drivers/acpi/acpica/utosi.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utresrc.c b/drivers/acpi/acpica/utresrc.c
index 6ffd3a8bdaa5..9d441ea70305 100644
--- a/drivers/acpi/acpica/utresrc.c
+++ b/drivers/acpi/acpica/utresrc.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -43,7 +43,7 @@
#include <acpi/acpi.h>
#include "accommon.h"
-#include "amlresrc.h"
+#include "acresrc.h"
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME("utresrc")
@@ -154,6 +154,138 @@ const char *acpi_gbl_typ_decode[] = {
"TypeF"
};
+const char *acpi_gbl_ppc_decode[] = {
+ "PullDefault",
+ "PullUp",
+ "PullDown",
+ "PullNone"
+};
+
+const char *acpi_gbl_ior_decode[] = {
+ "IoRestrictionNone",
+ "IoRestrictionInputOnly",
+ "IoRestrictionOutputOnly",
+ "IoRestrictionNoneAndPreserve"
+};
+
+const char *acpi_gbl_dts_decode[] = {
+ "Width8bit",
+ "Width16bit",
+ "Width32bit",
+ "Width64bit",
+ "Width128bit",
+ "Width256bit",
+};
+
+/* GPIO connection type */
+
+const char *acpi_gbl_ct_decode[] = {
+ "Interrupt",
+ "I/O"
+};
+
+/* Serial bus type */
+
+const char *acpi_gbl_sbt_decode[] = {
+ "/* UNKNOWN serial bus type */",
+ "I2C",
+ "SPI",
+ "UART"
+};
+
+/* I2C serial bus access mode */
+
+const char *acpi_gbl_am_decode[] = {
+ "AddressingMode7Bit",
+ "AddressingMode10Bit"
+};
+
+/* I2C serial bus slave mode */
+
+const char *acpi_gbl_sm_decode[] = {
+ "ControllerInitiated",
+ "DeviceInitiated"
+};
+
+/* SPI serial bus wire mode */
+
+const char *acpi_gbl_wm_decode[] = {
+ "FourWireMode",
+ "ThreeWireMode"
+};
+
+/* SPI serial clock phase */
+
+const char *acpi_gbl_cph_decode[] = {
+ "ClockPhaseFirst",
+ "ClockPhaseSecond"
+};
+
+/* SPI serial bus clock polarity */
+
+const char *acpi_gbl_cpo_decode[] = {
+ "ClockPolarityLow",
+ "ClockPolarityHigh"
+};
+
+/* SPI serial bus device polarity */
+
+const char *acpi_gbl_dp_decode[] = {
+ "PolarityLow",
+ "PolarityHigh"
+};
+
+/* UART serial bus endian */
+
+const char *acpi_gbl_ed_decode[] = {
+ "LittleEndian",
+ "BigEndian"
+};
+
+/* UART serial bus bits per byte */
+
+const char *acpi_gbl_bpb_decode[] = {
+ "DataBitsFive",
+ "DataBitsSix",
+ "DataBitsSeven",
+ "DataBitsEight",
+ "DataBitsNine",
+ "/* UNKNOWN Bits per byte */",
+ "/* UNKNOWN Bits per byte */",
+ "/* UNKNOWN Bits per byte */"
+};
+
+/* UART serial bus stop bits */
+
+const char *acpi_gbl_sb_decode[] = {
+ "StopBitsNone",
+ "StopBitsOne",
+ "StopBitsOnePlusHalf",
+ "StopBitsTwo"
+};
+
+/* UART serial bus flow control */
+
+const char *acpi_gbl_fc_decode[] = {
+ "FlowControlNone",
+ "FlowControlHardware",
+ "FlowControlXON",
+ "/* UNKNOWN flow control keyword */"
+};
+
+/* UART serial bus parity type */
+
+const char *acpi_gbl_pt_decode[] = {
+ "ParityTypeNone",
+ "ParityTypeEven",
+ "ParityTypeOdd",
+ "ParityTypeMark",
+ "ParityTypeSpace",
+ "/* UNKNOWN parity keyword */",
+ "/* UNKNOWN parity keyword */",
+ "/* UNKNOWN parity keyword */"
+};
+
#endif
/*
@@ -173,7 +305,7 @@ const u8 acpi_gbl_resource_aml_sizes[] = {
ACPI_AML_SIZE_SMALL(struct aml_resource_end_dependent),
ACPI_AML_SIZE_SMALL(struct aml_resource_io),
ACPI_AML_SIZE_SMALL(struct aml_resource_fixed_io),
- 0,
+ ACPI_AML_SIZE_SMALL(struct aml_resource_fixed_dma),
0,
0,
0,
@@ -193,7 +325,17 @@ const u8 acpi_gbl_resource_aml_sizes[] = {
ACPI_AML_SIZE_LARGE(struct aml_resource_address16),
ACPI_AML_SIZE_LARGE(struct aml_resource_extended_irq),
ACPI_AML_SIZE_LARGE(struct aml_resource_address64),
- ACPI_AML_SIZE_LARGE(struct aml_resource_extended_address64)
+ ACPI_AML_SIZE_LARGE(struct aml_resource_extended_address64),
+ ACPI_AML_SIZE_LARGE(struct aml_resource_gpio),
+ 0,
+ ACPI_AML_SIZE_LARGE(struct aml_resource_common_serialbus),
+};
+
+const u8 acpi_gbl_resource_aml_serial_bus_sizes[] = {
+ 0,
+ ACPI_AML_SIZE_LARGE(struct aml_resource_i2c_serialbus),
+ ACPI_AML_SIZE_LARGE(struct aml_resource_spi_serialbus),
+ ACPI_AML_SIZE_LARGE(struct aml_resource_uart_serialbus),
};
/*
@@ -209,35 +351,49 @@ static const u8 acpi_gbl_resource_types[] = {
0,
0,
0,
- ACPI_SMALL_VARIABLE_LENGTH,
- ACPI_FIXED_LENGTH,
- ACPI_SMALL_VARIABLE_LENGTH,
- ACPI_FIXED_LENGTH,
- ACPI_FIXED_LENGTH,
- ACPI_FIXED_LENGTH,
- 0,
+ ACPI_SMALL_VARIABLE_LENGTH, /* 04 IRQ */
+ ACPI_FIXED_LENGTH, /* 05 DMA */
+ ACPI_SMALL_VARIABLE_LENGTH, /* 06 start_dependent_functions */
+ ACPI_FIXED_LENGTH, /* 07 end_dependent_functions */
+ ACPI_FIXED_LENGTH, /* 08 IO */
+ ACPI_FIXED_LENGTH, /* 09 fixed_iO */
+ ACPI_FIXED_LENGTH, /* 0_a fixed_dMA */
0,
0,
0,
- ACPI_VARIABLE_LENGTH,
- ACPI_FIXED_LENGTH,
+ ACPI_VARIABLE_LENGTH, /* 0_e vendor_short */
+ ACPI_FIXED_LENGTH, /* 0_f end_tag */
/* Large descriptors */
0,
- ACPI_FIXED_LENGTH,
- ACPI_FIXED_LENGTH,
+ ACPI_FIXED_LENGTH, /* 01 Memory24 */
+ ACPI_FIXED_LENGTH, /* 02 generic_register */
0,
- ACPI_VARIABLE_LENGTH,
- ACPI_FIXED_LENGTH,
- ACPI_FIXED_LENGTH,
- ACPI_VARIABLE_LENGTH,
- ACPI_VARIABLE_LENGTH,
- ACPI_VARIABLE_LENGTH,
- ACPI_VARIABLE_LENGTH,
- ACPI_FIXED_LENGTH
+ ACPI_VARIABLE_LENGTH, /* 04 vendor_long */
+ ACPI_FIXED_LENGTH, /* 05 Memory32 */
+ ACPI_FIXED_LENGTH, /* 06 memory32_fixed */
+ ACPI_VARIABLE_LENGTH, /* 07 Dword* address */
+ ACPI_VARIABLE_LENGTH, /* 08 Word* address */
+ ACPI_VARIABLE_LENGTH, /* 09 extended_iRQ */
+ ACPI_VARIABLE_LENGTH, /* 0_a Qword* address */
+ ACPI_FIXED_LENGTH, /* 0_b Extended* address */
+ ACPI_VARIABLE_LENGTH, /* 0_c Gpio* */
+ 0,
+ ACPI_VARIABLE_LENGTH /* 0_e *serial_bus */
};
+/*
+ * For the i_aSL compiler/disassembler, we don't want any error messages
+ * because the disassembler uses the resource validation code to determine
+ * if Buffer objects are actually Resource Templates.
+ */
+#ifdef ACPI_ASL_COMPILER
+#define ACPI_RESOURCE_ERROR(plist)
+#else
+#define ACPI_RESOURCE_ERROR(plist) ACPI_ERROR(plist)
+#endif
+
/*******************************************************************************
*
* FUNCTION: acpi_ut_walk_aml_resources
@@ -265,6 +421,7 @@ acpi_ut_walk_aml_resources(u8 * aml,
u8 resource_index;
u32 length;
u32 offset = 0;
+ u8 end_tag[2] = { 0x79, 0x00 };
ACPI_FUNCTION_TRACE(ut_walk_aml_resources);
@@ -286,6 +443,10 @@ acpi_ut_walk_aml_resources(u8 * aml,
status = acpi_ut_validate_resource(aml, &resource_index);
if (ACPI_FAILURE(status)) {
+ /*
+ * Exit on failure. Cannot continue because the descriptor length
+ * may be bogus also.
+ */
return_ACPI_STATUS(status);
}
@@ -300,7 +461,7 @@ acpi_ut_walk_aml_resources(u8 * aml,
user_function(aml, length, offset, resource_index,
context);
if (ACPI_FAILURE(status)) {
- return (status);
+ return_ACPI_STATUS(status);
}
}
@@ -333,7 +494,19 @@ acpi_ut_walk_aml_resources(u8 * aml,
/* Did not find an end_tag descriptor */
- return (AE_AML_NO_RESOURCE_END_TAG);
+ if (user_function) {
+
+ /* Insert an end_tag anyway. acpi_rs_get_list_length always leaves room */
+
+ (void)acpi_ut_validate_resource(end_tag, &resource_index);
+ status =
+ user_function(end_tag, 2, offset, resource_index, context);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+ }
+
+ return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
}
/*******************************************************************************
@@ -354,6 +527,7 @@ acpi_ut_walk_aml_resources(u8 * aml,
acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index)
{
+ union aml_resource *aml_resource;
u8 resource_type;
u8 resource_index;
acpi_rs_length resource_length;
@@ -375,7 +549,7 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index)
/* Verify the large resource type (name) against the max */
if (resource_type > ACPI_RESOURCE_NAME_LARGE_MAX) {
- return (AE_AML_INVALID_RESOURCE_TYPE);
+ goto invalid_resource;
}
/*
@@ -392,15 +566,17 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index)
((resource_type & ACPI_RESOURCE_NAME_SMALL_MASK) >> 3);
}
- /* Check validity of the resource type, zero indicates name is invalid */
-
+ /*
+ * Check validity of the resource type, via acpi_gbl_resource_types. Zero
+ * indicates an invalid resource.
+ */
if (!acpi_gbl_resource_types[resource_index]) {
- return (AE_AML_INVALID_RESOURCE_TYPE);
+ goto invalid_resource;
}
/*
- * 2) Validate the resource_length field. This ensures that the length
- * is at least reasonable, and guarantees that it is non-zero.
+ * Validate the resource_length field. This ensures that the length
+ * is at least reasonable, and guarantees that it is non-zero.
*/
resource_length = acpi_ut_get_resource_length(aml);
minimum_resource_length = acpi_gbl_resource_aml_sizes[resource_index];
@@ -413,7 +589,7 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index)
/* Fixed length resource, length must match exactly */
if (resource_length != minimum_resource_length) {
- return (AE_AML_BAD_RESOURCE_LENGTH);
+ goto bad_resource_length;
}
break;
@@ -422,7 +598,7 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index)
/* Variable length resource, length must be at least the minimum */
if (resource_length < minimum_resource_length) {
- return (AE_AML_BAD_RESOURCE_LENGTH);
+ goto bad_resource_length;
}
break;
@@ -432,7 +608,7 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index)
if ((resource_length > minimum_resource_length) ||
(resource_length < (minimum_resource_length - 1))) {
- return (AE_AML_BAD_RESOURCE_LENGTH);
+ goto bad_resource_length;
}
break;
@@ -440,7 +616,23 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index)
/* Shouldn't happen (because of validation earlier), but be sure */
- return (AE_AML_INVALID_RESOURCE_TYPE);
+ goto invalid_resource;
+ }
+
+ aml_resource = ACPI_CAST_PTR(union aml_resource, aml);
+ if (resource_type == ACPI_RESOURCE_NAME_SERIAL_BUS) {
+
+ /* Validate the bus_type field */
+
+ if ((aml_resource->common_serial_bus.type == 0) ||
+ (aml_resource->common_serial_bus.type >
+ AML_RESOURCE_MAX_SERIALBUSTYPE)) {
+ ACPI_RESOURCE_ERROR((AE_INFO,
+ "Invalid/unsupported SerialBus resource descriptor: BusType 0x%2.2X",
+ aml_resource->common_serial_bus.
+ type));
+ return (AE_AML_INVALID_RESOURCE_TYPE);
+ }
}
/* Optionally return the resource table index */
@@ -450,6 +642,22 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index)
}
return (AE_OK);
+
+ invalid_resource:
+
+ ACPI_RESOURCE_ERROR((AE_INFO,
+ "Invalid/unsupported resource descriptor: Type 0x%2.2X",
+ resource_type));
+ return (AE_AML_INVALID_RESOURCE_TYPE);
+
+ bad_resource_length:
+
+ ACPI_RESOURCE_ERROR((AE_INFO,
+ "Invalid resource descriptor length: Type "
+ "0x%2.2X, Length 0x%4.4X, MinLength 0x%4.4X",
+ resource_type, resource_length,
+ minimum_resource_length));
+ return (AE_AML_BAD_RESOURCE_LENGTH);
}
/*******************************************************************************
diff --git a/drivers/acpi/acpica/utstate.c b/drivers/acpi/acpica/utstate.c
index 30c21e1a9360..4267477c2797 100644
--- a/drivers/acpi/acpica/utstate.c
+++ b/drivers/acpi/acpica/utstate.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c
index 420ebfe08c72..644e8c8ebc4b 100644
--- a/drivers/acpi/acpica/utxface.c
+++ b/drivers/acpi/acpica/utxface.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -48,6 +48,7 @@
#include "acnamesp.h"
#include "acdebug.h"
#include "actables.h"
+#include "acinterp.h"
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME("utxface")
@@ -640,4 +641,41 @@ acpi_status acpi_install_interface_handler(acpi_interface_handler handler)
}
ACPI_EXPORT_SYMBOL(acpi_install_interface_handler)
+
+/*****************************************************************************
+ *
+ * FUNCTION: acpi_check_address_range
+ *
+ * PARAMETERS: space_id - Address space ID
+ * Address - Start address
+ * Length - Length
+ * Warn - TRUE if warning on overlap desired
+ *
+ * RETURN: Count of the number of conflicts detected.
+ *
+ * DESCRIPTION: Check if the input address range overlaps any of the
+ * ASL operation region address ranges.
+ *
+ ****************************************************************************/
+u32
+acpi_check_address_range(acpi_adr_space_type space_id,
+ acpi_physical_address address,
+ acpi_size length, u8 warn)
+{
+ u32 overlaps;
+ acpi_status status;
+
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return (0);
+ }
+
+ overlaps = acpi_ut_check_address_range(space_id, address,
+ (u32)length, warn);
+
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return (overlaps);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_check_address_range)
#endif /* !ACPI_ASL_COMPILER */
diff --git a/drivers/acpi/acpica/utxferror.c b/drivers/acpi/acpica/utxferror.c
index 8d0245ec4315..52b568af1819 100644
--- a/drivers/acpi/acpica/utxferror.c
+++ b/drivers/acpi/acpica/utxferror.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2012, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/drivers/acpi/acpica/utxfmutex.c b/drivers/acpi/acpica/utxfmutex.c
new file mode 100644
index 000000000000..1427d191d15a
--- /dev/null
+++ b/drivers/acpi/acpica/utxfmutex.c
@@ -0,0 +1,187 @@
+/*******************************************************************************
+ *
+ * Module Name: utxfmutex - external AML mutex access functions
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2012, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "acnamesp.h"
+
+#define _COMPONENT ACPI_UTILITIES
+ACPI_MODULE_NAME("utxfmutex")
+
+/* Local prototypes */
+static acpi_status
+acpi_ut_get_mutex_object(acpi_handle handle,
+ acpi_string pathname,
+ union acpi_operand_object **ret_obj);
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_get_mutex_object
+ *
+ * PARAMETERS: Handle - Mutex or prefix handle (optional)
+ * Pathname - Mutex pathname (optional)
+ * ret_obj - Where the mutex object is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Get an AML mutex object. The mutex node is pointed to by
+ * Handle:Pathname. Either Handle or Pathname can be NULL, but
+ * not both.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ut_get_mutex_object(acpi_handle handle,
+ acpi_string pathname,
+ union acpi_operand_object **ret_obj)
+{
+ struct acpi_namespace_node *mutex_node;
+ union acpi_operand_object *mutex_obj;
+ acpi_status status;
+
+ /* Parameter validation */
+
+ if (!ret_obj || (!handle && !pathname)) {
+ return (AE_BAD_PARAMETER);
+ }
+
+ /* Get a the namespace node for the mutex */
+
+ mutex_node = handle;
+ if (pathname != NULL) {
+ status = acpi_get_handle(handle, pathname,
+ ACPI_CAST_PTR(acpi_handle,
+ &mutex_node));
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+ }
+
+ /* Ensure that we actually have a Mutex object */
+
+ if (!mutex_node || (mutex_node->type != ACPI_TYPE_MUTEX)) {
+ return (AE_TYPE);
+ }
+
+ /* Get the low-level mutex object */
+
+ mutex_obj = acpi_ns_get_attached_object(mutex_node);
+ if (!mutex_obj) {
+ return (AE_NULL_OBJECT);
+ }
+
+ *ret_obj = mutex_obj;
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_acquire_mutex
+ *
+ * PARAMETERS: Handle - Mutex or prefix handle (optional)
+ * Pathname - Mutex pathname (optional)
+ * Timeout - Max time to wait for the lock (millisec)
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Acquire an AML mutex. This is a device driver interface to
+ * AML mutex objects, and allows for transaction locking between
+ * drivers and AML code. The mutex node is pointed to by
+ * Handle:Pathname. Either Handle or Pathname can be NULL, but
+ * not both.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_acquire_mutex(acpi_handle handle, acpi_string pathname, u16 timeout)
+{
+ acpi_status status;
+ union acpi_operand_object *mutex_obj;
+
+ /* Get the low-level mutex associated with Handle:Pathname */
+
+ status = acpi_ut_get_mutex_object(handle, pathname, &mutex_obj);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ /* Acquire the OS mutex */
+
+ status = acpi_os_acquire_mutex(mutex_obj->mutex.os_mutex, timeout);
+ return (status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_release_mutex
+ *
+ * PARAMETERS: Handle - Mutex or prefix handle (optional)
+ * Pathname - Mutex pathname (optional)
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Release an AML mutex. This is a device driver interface to
+ * AML mutex objects, and allows for transaction locking between
+ * drivers and AML code. The mutex node is pointed to by
+ * Handle:Pathname. Either Handle or Pathname can be NULL, but
+ * not both.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_release_mutex(acpi_handle handle, acpi_string pathname)
+{
+ acpi_status status;
+ union acpi_operand_object *mutex_obj;
+
+ /* Get the low-level mutex associated with Handle:Pathname */
+
+ status = acpi_ut_get_mutex_object(handle, pathname, &mutex_obj);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ /* Release the OS mutex */
+
+ acpi_os_release_mutex(mutex_obj->mutex.os_mutex);
+ return (AE_OK);
+}
diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c
index 61540360d5ce..e45350cb6ac8 100644
--- a/drivers/acpi/apei/apei-base.c
+++ b/drivers/acpi/apei/apei-base.c
@@ -34,13 +34,13 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/acpi.h>
+#include <linux/acpi_io.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/kref.h>
#include <linux/rculist.h>
#include <linux/interrupt.h>
#include <linux/debugfs.h>
-#include <acpi/atomicio.h>
#include "apei-internal.h"
@@ -70,7 +70,7 @@ int __apei_exec_read_register(struct acpi_whea_header *entry, u64 *val)
{
int rc;
- rc = acpi_atomic_read(val, &entry->register_region);
+ rc = apei_read(val, &entry->register_region);
if (rc)
return rc;
*val >>= entry->register_region.bit_offset;
@@ -116,13 +116,13 @@ int __apei_exec_write_register(struct acpi_whea_header *entry, u64 val)
val <<= entry->register_region.bit_offset;
if (entry->flags & APEI_EXEC_PRESERVE_REGISTER) {
u64 valr = 0;
- rc = acpi_atomic_read(&valr, &entry->register_region);
+ rc = apei_read(&valr, &entry->register_region);
if (rc)
return rc;
valr &= ~(entry->mask << entry->register_region.bit_offset);
val |= valr;
}
- rc = acpi_atomic_write(val, &entry->register_region);
+ rc = apei_write(val, &entry->register_region);
return rc;
}
@@ -243,7 +243,7 @@ static int pre_map_gar_callback(struct apei_exec_context *ctx,
u8 ins = entry->instruction;
if (ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER)
- return acpi_pre_map_gar(&entry->register_region);
+ return acpi_os_map_generic_address(&entry->register_region);
return 0;
}
@@ -276,7 +276,7 @@ static int post_unmap_gar_callback(struct apei_exec_context *ctx,
u8 ins = entry->instruction;
if (ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER)
- acpi_post_unmap_gar(&entry->register_region);
+ acpi_os_unmap_generic_address(&entry->register_region);
return 0;
}
@@ -421,6 +421,17 @@ static int apei_resources_merge(struct apei_resources *resources1,
return 0;
}
+int apei_resources_add(struct apei_resources *resources,
+ unsigned long start, unsigned long size,
+ bool iomem)
+{
+ if (iomem)
+ return apei_res_add(&resources->iomem, start, size);
+ else
+ return apei_res_add(&resources->ioport, start, size);
+}
+EXPORT_SYMBOL_GPL(apei_resources_add);
+
/*
* EINJ has two groups of GARs (EINJ table entry and trigger table
* entry), so common resources are subtracted from the trigger table
@@ -438,8 +449,19 @@ int apei_resources_sub(struct apei_resources *resources1,
}
EXPORT_SYMBOL_GPL(apei_resources_sub);
+static int apei_get_nvs_callback(__u64 start, __u64 size, void *data)
+{
+ struct apei_resources *resources = data;
+ return apei_res_add(&resources->iomem, start, size);
+}
+
+static int apei_get_nvs_resources(struct apei_resources *resources)
+{
+ return acpi_nvs_for_each_region(apei_get_nvs_callback, resources);
+}
+
/*
- * IO memory/port rersource management mechanism is used to check
+ * IO memory/port resource management mechanism is used to check
* whether memory/port area used by GARs conflicts with normal memory
* or IO memory/port of devices.
*/
@@ -448,21 +470,35 @@ int apei_resources_request(struct apei_resources *resources,
{
struct apei_res *res, *res_bak = NULL;
struct resource *r;
+ struct apei_resources nvs_resources;
int rc;
rc = apei_resources_sub(resources, &apei_resources_all);
if (rc)
return rc;
+ /*
+ * Some firmware uses ACPI NVS region, that has been marked as
+ * busy, so exclude it from APEI resources to avoid false
+ * conflict.
+ */
+ apei_resources_init(&nvs_resources);
+ rc = apei_get_nvs_resources(&nvs_resources);
+ if (rc)
+ goto res_fini;
+ rc = apei_resources_sub(resources, &nvs_resources);
+ if (rc)
+ goto res_fini;
+
rc = -EINVAL;
list_for_each_entry(res, &resources->iomem, list) {
r = request_mem_region(res->start, res->end - res->start,
desc);
if (!r) {
pr_err(APEI_PFX
- "Can not request iomem region <%016llx-%016llx> for GARs.\n",
+ "Can not request [mem %#010llx-%#010llx] for %s registers\n",
(unsigned long long)res->start,
- (unsigned long long)res->end);
+ (unsigned long long)res->end - 1, desc);
res_bak = res;
goto err_unmap_iomem;
}
@@ -472,9 +508,9 @@ int apei_resources_request(struct apei_resources *resources,
r = request_region(res->start, res->end - res->start, desc);
if (!r) {
pr_err(APEI_PFX
- "Can not request ioport region <%016llx-%016llx> for GARs.\n",
+ "Can not request [io %#06llx-%#06llx] for %s registers\n",
(unsigned long long)res->start,
- (unsigned long long)res->end);
+ (unsigned long long)res->end - 1, desc);
res_bak = res;
goto err_unmap_ioport;
}
@@ -500,6 +536,8 @@ err_unmap_iomem:
break;
release_mem_region(res->start, res->end - res->start);
}
+res_fini:
+ apei_resources_fini(&nvs_resources);
return rc;
}
EXPORT_SYMBOL_GPL(apei_resources_request);
@@ -553,6 +591,96 @@ static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr)
return 0;
}
+/* read GAR in interrupt (including NMI) or process context */
+int apei_read(u64 *val, struct acpi_generic_address *reg)
+{
+ int rc;
+ u64 address;
+ u32 tmp, width = reg->bit_width;
+ acpi_status status;
+
+ rc = apei_check_gar(reg, &address);
+ if (rc)
+ return rc;
+
+ if (width == 64)
+ width = 32; /* Break into two 32-bit transfers */
+
+ *val = 0;
+ switch(reg->space_id) {
+ case ACPI_ADR_SPACE_SYSTEM_MEMORY:
+ status = acpi_os_read_memory((acpi_physical_address)
+ address, &tmp, width);
+ if (ACPI_FAILURE(status))
+ return -EIO;
+ *val = tmp;
+
+ if (reg->bit_width == 64) {
+ /* Read the top 32 bits */
+ status = acpi_os_read_memory((acpi_physical_address)
+ (address + 4), &tmp, 32);
+ if (ACPI_FAILURE(status))
+ return -EIO;
+ *val |= ((u64)tmp << 32);
+ }
+ break;
+ case ACPI_ADR_SPACE_SYSTEM_IO:
+ status = acpi_os_read_port(address, (u32 *)val, reg->bit_width);
+ if (ACPI_FAILURE(status))
+ return -EIO;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(apei_read);
+
+/* write GAR in interrupt (including NMI) or process context */
+int apei_write(u64 val, struct acpi_generic_address *reg)
+{
+ int rc;
+ u64 address;
+ u32 width = reg->bit_width;
+ acpi_status status;
+
+ rc = apei_check_gar(reg, &address);
+ if (rc)
+ return rc;
+
+ if (width == 64)
+ width = 32; /* Break into two 32-bit transfers */
+
+ switch (reg->space_id) {
+ case ACPI_ADR_SPACE_SYSTEM_MEMORY:
+ status = acpi_os_write_memory((acpi_physical_address)
+ address, ACPI_LODWORD(val),
+ width);
+ if (ACPI_FAILURE(status))
+ return -EIO;
+
+ if (reg->bit_width == 64) {
+ status = acpi_os_write_memory((acpi_physical_address)
+ (address + 4),
+ ACPI_HIDWORD(val), 32);
+ if (ACPI_FAILURE(status))
+ return -EIO;
+ }
+ break;
+ case ACPI_ADR_SPACE_SYSTEM_IO:
+ status = acpi_os_write_port(address, val, reg->bit_width);
+ if (ACPI_FAILURE(status))
+ return -EIO;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(apei_write);
+
static int collect_res_callback(struct apei_exec_context *ctx,
struct acpi_whea_header *entry,
void *data)
diff --git a/drivers/acpi/apei/apei-internal.h b/drivers/acpi/apei/apei-internal.h
index f57050e7a5e7..cca240a33038 100644
--- a/drivers/acpi/apei/apei-internal.h
+++ b/drivers/acpi/apei/apei-internal.h
@@ -68,6 +68,9 @@ static inline int apei_exec_run_optional(struct apei_exec_context *ctx, u8 actio
/* IP has been set in instruction function */
#define APEI_EXEC_SET_IP 1
+int apei_read(u64 *val, struct acpi_generic_address *reg);
+int apei_write(u64 val, struct acpi_generic_address *reg);
+
int __apei_exec_read_register(struct acpi_whea_header *entry, u64 *val);
int __apei_exec_write_register(struct acpi_whea_header *entry, u64 val);
int apei_exec_read_register(struct apei_exec_context *ctx,
@@ -95,6 +98,9 @@ static inline void apei_resources_init(struct apei_resources *resources)
}
void apei_resources_fini(struct apei_resources *resources);
+int apei_resources_add(struct apei_resources *resources,
+ unsigned long start, unsigned long size,
+ bool iomem);
int apei_resources_sub(struct apei_resources *resources1,
struct apei_resources *resources2);
int apei_resources_request(struct apei_resources *resources,
diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c
index 589b96c38704..5b898d4dda99 100644
--- a/drivers/acpi/apei/einj.c
+++ b/drivers/acpi/apei/einj.c
@@ -43,6 +43,42 @@
#define FIRMWARE_TIMEOUT (1 * NSEC_PER_MSEC)
/*
+ * ACPI version 5 provides a SET_ERROR_TYPE_WITH_ADDRESS action.
+ */
+static int acpi5;
+
+struct set_error_type_with_address {
+ u32 type;
+ u32 vendor_extension;
+ u32 flags;
+ u32 apicid;
+ u64 memory_address;
+ u64 memory_address_range;
+ u32 pcie_sbdf;
+};
+enum {
+ SETWA_FLAGS_APICID = 1,
+ SETWA_FLAGS_MEM = 2,
+ SETWA_FLAGS_PCIE_SBDF = 4,
+};
+
+/*
+ * Vendor extensions for platform specific operations
+ */
+struct vendor_error_type_extension {
+ u32 length;
+ u32 pcie_sbdf;
+ u16 vendor_id;
+ u16 device_id;
+ u8 rev_id;
+ u8 reserved[3];
+};
+
+static u32 vendor_flags;
+static struct debugfs_blob_wrapper vendor_blob;
+static char vendor_dev[64];
+
+/*
* Some BIOSes allow parameters to the SET_ERROR_TYPE entries in the
* EINJ table through an unpublished extension. Use with caution as
* most will ignore the parameter and make their own choice of address
@@ -103,7 +139,14 @@ static struct apei_exec_ins_type einj_ins_type[] = {
*/
static DEFINE_MUTEX(einj_mutex);
-static struct einj_parameter *einj_param;
+static void *einj_param;
+
+#ifndef readq
+static inline __u64 readq(volatile void __iomem *addr)
+{
+ return ((__u64)readl(addr+4) << 32) + readl(addr);
+}
+#endif
#ifndef writeq
static inline void writeq(__u64 val, volatile void __iomem *addr)
@@ -158,10 +201,31 @@ static int einj_timedout(u64 *t)
return 0;
}
-static u64 einj_get_parameter_address(void)
+static void check_vendor_extension(u64 paddr,
+ struct set_error_type_with_address *v5param)
+{
+ int offset = readl(&v5param->vendor_extension);
+ struct vendor_error_type_extension *v;
+ u32 sbdf;
+
+ if (!offset)
+ return;
+ v = ioremap(paddr + offset, sizeof(*v));
+ if (!v)
+ return;
+ sbdf = readl(&v->pcie_sbdf);
+ sprintf(vendor_dev, "%x:%x:%x.%x vendor_id=%x device_id=%x rev_id=%x\n",
+ sbdf >> 24, (sbdf >> 16) & 0xff,
+ (sbdf >> 11) & 0x1f, (sbdf >> 8) & 0x7,
+ readw(&v->vendor_id), readw(&v->device_id),
+ readb(&v->rev_id));
+ iounmap(v);
+}
+
+static void *einj_get_parameter_address(void)
{
int i;
- u64 paddr = 0;
+ u64 paddrv4 = 0, paddrv5 = 0;
struct acpi_whea_header *entry;
entry = EINJ_TAB_ENTRY(einj_tab);
@@ -170,12 +234,40 @@ static u64 einj_get_parameter_address(void)
entry->instruction == ACPI_EINJ_WRITE_REGISTER &&
entry->register_region.space_id ==
ACPI_ADR_SPACE_SYSTEM_MEMORY)
- memcpy(&paddr, &entry->register_region.address,
- sizeof(paddr));
+ memcpy(&paddrv4, &entry->register_region.address,
+ sizeof(paddrv4));
+ if (entry->action == ACPI_EINJ_SET_ERROR_TYPE_WITH_ADDRESS &&
+ entry->instruction == ACPI_EINJ_WRITE_REGISTER &&
+ entry->register_region.space_id ==
+ ACPI_ADR_SPACE_SYSTEM_MEMORY)
+ memcpy(&paddrv5, &entry->register_region.address,
+ sizeof(paddrv5));
entry++;
}
+ if (paddrv5) {
+ struct set_error_type_with_address *v5param;
+
+ v5param = ioremap(paddrv5, sizeof(*v5param));
+ if (v5param) {
+ acpi5 = 1;
+ check_vendor_extension(paddrv5, v5param);
+ return v5param;
+ }
+ }
+ if (paddrv4) {
+ struct einj_parameter *v4param;
+
+ v4param = ioremap(paddrv4, sizeof(*v4param));
+ if (!v4param)
+ return 0;
+ if (readq(&v4param->reserved1) || readq(&v4param->reserved2)) {
+ iounmap(v4param);
+ return 0;
+ }
+ return v4param;
+ }
- return paddr;
+ return 0;
}
/* do sanity check to trigger table */
@@ -194,8 +286,29 @@ static int einj_check_trigger_header(struct acpi_einj_trigger *trigger_tab)
return 0;
}
+static struct acpi_generic_address *einj_get_trigger_parameter_region(
+ struct acpi_einj_trigger *trigger_tab, u64 param1, u64 param2)
+{
+ int i;
+ struct acpi_whea_header *entry;
+
+ entry = (struct acpi_whea_header *)
+ ((char *)trigger_tab + sizeof(struct acpi_einj_trigger));
+ for (i = 0; i < trigger_tab->entry_count; i++) {
+ if (entry->action == ACPI_EINJ_TRIGGER_ERROR &&
+ entry->instruction == ACPI_EINJ_WRITE_REGISTER_VALUE &&
+ entry->register_region.space_id ==
+ ACPI_ADR_SPACE_SYSTEM_MEMORY &&
+ (entry->register_region.address & param2) == (param1 & param2))
+ return &entry->register_region;
+ entry++;
+ }
+
+ return NULL;
+}
/* Execute instructions in trigger error action table */
-static int __einj_error_trigger(u64 trigger_paddr)
+static int __einj_error_trigger(u64 trigger_paddr, u32 type,
+ u64 param1, u64 param2)
{
struct acpi_einj_trigger *trigger_tab = NULL;
struct apei_exec_context trigger_ctx;
@@ -204,14 +317,16 @@ static int __einj_error_trigger(u64 trigger_paddr)
struct resource *r;
u32 table_size;
int rc = -EIO;
+ struct acpi_generic_address *trigger_param_region = NULL;
r = request_mem_region(trigger_paddr, sizeof(*trigger_tab),
"APEI EINJ Trigger Table");
if (!r) {
pr_err(EINJ_PFX
- "Can not request iomem region <%016llx-%016llx> for Trigger table.\n",
+ "Can not request [mem %#010llx-%#010llx] for Trigger table\n",
(unsigned long long)trigger_paddr,
- (unsigned long long)trigger_paddr+sizeof(*trigger_tab));
+ (unsigned long long)trigger_paddr +
+ sizeof(*trigger_tab) - 1);
goto out;
}
trigger_tab = ioremap_cache(trigger_paddr, sizeof(*trigger_tab));
@@ -232,9 +347,9 @@ static int __einj_error_trigger(u64 trigger_paddr)
"APEI EINJ Trigger Table");
if (!r) {
pr_err(EINJ_PFX
-"Can not request iomem region <%016llx-%016llx> for Trigger Table Entry.\n",
- (unsigned long long)trigger_paddr+sizeof(*trigger_tab),
- (unsigned long long)trigger_paddr + table_size);
+"Can not request [mem %#010llx-%#010llx] for Trigger Table Entry\n",
+ (unsigned long long)trigger_paddr + sizeof(*trigger_tab),
+ (unsigned long long)trigger_paddr + table_size - 1);
goto out_rel_header;
}
iounmap(trigger_tab);
@@ -255,6 +370,30 @@ static int __einj_error_trigger(u64 trigger_paddr)
rc = apei_resources_sub(&trigger_resources, &einj_resources);
if (rc)
goto out_fini;
+ /*
+ * Some firmware will access target address specified in
+ * param1 to trigger the error when injecting memory error.
+ * This will cause resource conflict with regular memory. So
+ * remove it from trigger table resources.
+ */
+ if (param_extension && (type & 0x0038) && param2) {
+ struct apei_resources addr_resources;
+ apei_resources_init(&addr_resources);
+ trigger_param_region = einj_get_trigger_parameter_region(
+ trigger_tab, param1, param2);
+ if (trigger_param_region) {
+ rc = apei_resources_add(&addr_resources,
+ trigger_param_region->address,
+ trigger_param_region->bit_width/8, true);
+ if (rc)
+ goto out_fini;
+ rc = apei_resources_sub(&trigger_resources,
+ &addr_resources);
+ }
+ apei_resources_fini(&addr_resources);
+ if (rc)
+ goto out_fini;
+ }
rc = apei_resources_request(&trigger_resources, "APEI EINJ Trigger");
if (rc)
goto out_fini;
@@ -293,12 +432,56 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2)
if (rc)
return rc;
apei_exec_ctx_set_input(&ctx, type);
- rc = apei_exec_run(&ctx, ACPI_EINJ_SET_ERROR_TYPE);
- if (rc)
- return rc;
- if (einj_param) {
- writeq(param1, &einj_param->param1);
- writeq(param2, &einj_param->param2);
+ if (acpi5) {
+ struct set_error_type_with_address *v5param = einj_param;
+
+ writel(type, &v5param->type);
+ if (type & 0x80000000) {
+ switch (vendor_flags) {
+ case SETWA_FLAGS_APICID:
+ writel(param1, &v5param->apicid);
+ break;
+ case SETWA_FLAGS_MEM:
+ writeq(param1, &v5param->memory_address);
+ writeq(param2, &v5param->memory_address_range);
+ break;
+ case SETWA_FLAGS_PCIE_SBDF:
+ writel(param1, &v5param->pcie_sbdf);
+ break;
+ }
+ writel(vendor_flags, &v5param->flags);
+ } else {
+ switch (type) {
+ case ACPI_EINJ_PROCESSOR_CORRECTABLE:
+ case ACPI_EINJ_PROCESSOR_UNCORRECTABLE:
+ case ACPI_EINJ_PROCESSOR_FATAL:
+ writel(param1, &v5param->apicid);
+ writel(SETWA_FLAGS_APICID, &v5param->flags);
+ break;
+ case ACPI_EINJ_MEMORY_CORRECTABLE:
+ case ACPI_EINJ_MEMORY_UNCORRECTABLE:
+ case ACPI_EINJ_MEMORY_FATAL:
+ writeq(param1, &v5param->memory_address);
+ writeq(param2, &v5param->memory_address_range);
+ writel(SETWA_FLAGS_MEM, &v5param->flags);
+ break;
+ case ACPI_EINJ_PCIX_CORRECTABLE:
+ case ACPI_EINJ_PCIX_UNCORRECTABLE:
+ case ACPI_EINJ_PCIX_FATAL:
+ writel(param1, &v5param->pcie_sbdf);
+ writel(SETWA_FLAGS_PCIE_SBDF, &v5param->flags);
+ break;
+ }
+ }
+ } else {
+ rc = apei_exec_run(&ctx, ACPI_EINJ_SET_ERROR_TYPE);
+ if (rc)
+ return rc;
+ if (einj_param) {
+ struct einj_parameter *v4param = einj_param;
+ writeq(param1, &v4param->param1);
+ writeq(param2, &v4param->param2);
+ }
}
rc = apei_exec_run(&ctx, ACPI_EINJ_EXECUTE_OPERATION);
if (rc)
@@ -324,7 +507,7 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2)
if (rc)
return rc;
trigger_paddr = apei_exec_ctx_get_output(&ctx);
- rc = __einj_error_trigger(trigger_paddr);
+ rc = __einj_error_trigger(trigger_paddr, type, param1, param2);
if (rc)
return rc;
rc = apei_exec_run_optional(&ctx, ACPI_EINJ_END_OPERATION);
@@ -408,15 +591,25 @@ static int error_type_set(void *data, u64 val)
{
int rc;
u32 available_error_type = 0;
+ u32 tval, vendor;
+
+ /*
+ * Vendor defined types have 0x80000000 bit set, and
+ * are not enumerated by ACPI_EINJ_GET_ERROR_TYPE
+ */
+ vendor = val & 0x80000000;
+ tval = val & 0x7fffffff;
/* Only one error type can be specified */
- if (val & (val - 1))
- return -EINVAL;
- rc = einj_get_available_error_type(&available_error_type);
- if (rc)
- return rc;
- if (!(val & available_error_type))
+ if (tval & (tval - 1))
return -EINVAL;
+ if (!vendor) {
+ rc = einj_get_available_error_type(&available_error_type);
+ if (rc)
+ return rc;
+ if (!(val & available_error_type))
+ return -EINVAL;
+ }
error_type = val;
return 0;
@@ -455,7 +648,6 @@ static int einj_check_table(struct acpi_table_einj *einj_tab)
static int __init einj_init(void)
{
int rc;
- u64 param_paddr;
acpi_status status;
struct dentry *fentry;
struct apei_exec_context ctx;
@@ -465,10 +657,9 @@ static int __init einj_init(void)
status = acpi_get_table(ACPI_SIG_EINJ, 0,
(struct acpi_table_header **)&einj_tab);
- if (status == AE_NOT_FOUND) {
- pr_info(EINJ_PFX "Table is not found!\n");
+ if (status == AE_NOT_FOUND)
return -ENODEV;
- } else if (ACPI_FAILURE(status)) {
+ else if (ACPI_FAILURE(status)) {
const char *msg = acpi_format_exception(status);
pr_err(EINJ_PFX "Failed to get table, %s\n", msg);
return -EINVAL;
@@ -509,23 +700,30 @@ static int __init einj_init(void)
rc = apei_exec_pre_map_gars(&ctx);
if (rc)
goto err_release;
- if (param_extension) {
- param_paddr = einj_get_parameter_address();
- if (param_paddr) {
- einj_param = ioremap(param_paddr, sizeof(*einj_param));
- rc = -ENOMEM;
- if (!einj_param)
- goto err_unmap;
- fentry = debugfs_create_x64("param1", S_IRUSR | S_IWUSR,
- einj_debug_dir, &error_param1);
- if (!fentry)
- goto err_unmap;
- fentry = debugfs_create_x64("param2", S_IRUSR | S_IWUSR,
- einj_debug_dir, &error_param2);
- if (!fentry)
- goto err_unmap;
- } else
- pr_warn(EINJ_PFX "Parameter extension is not supported.\n");
+
+ einj_param = einj_get_parameter_address();
+ if ((param_extension || acpi5) && einj_param) {
+ fentry = debugfs_create_x64("param1", S_IRUSR | S_IWUSR,
+ einj_debug_dir, &error_param1);
+ if (!fentry)
+ goto err_unmap;
+ fentry = debugfs_create_x64("param2", S_IRUSR | S_IWUSR,
+ einj_debug_dir, &error_param2);
+ if (!fentry)
+ goto err_unmap;
+ }
+
+ if (vendor_dev[0]) {
+ vendor_blob.data = vendor_dev;
+ vendor_blob.size = strlen(vendor_dev);
+ fentry = debugfs_create_blob("vendor", S_IRUSR,
+ einj_debug_dir, &vendor_blob);
+ if (!fentry)
+ goto err_unmap;
+ fentry = debugfs_create_x32("vendor_flags", S_IRUSR | S_IWUSR,
+ einj_debug_dir, &vendor_flags);
+ if (!fentry)
+ goto err_unmap;
}
pr_info(EINJ_PFX "Error INJection is initialized.\n");
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
index 6a9e3bad13f4..eb9fab5b96e4 100644
--- a/drivers/acpi/apei/erst.c
+++ b/drivers/acpi/apei/erst.c
@@ -1127,10 +1127,9 @@ static int __init erst_init(void)
status = acpi_get_table(ACPI_SIG_ERST, 0,
(struct acpi_table_header **)&erst_tab);
- if (status == AE_NOT_FOUND) {
- pr_info(ERST_PFX "Table is not found!\n");
+ if (status == AE_NOT_FOUND)
goto err;
- } else if (ACPI_FAILURE(status)) {
+ else if (ACPI_FAILURE(status)) {
const char *msg = acpi_format_exception(status);
pr_err(ERST_PFX "Failed to get table, %s\n", msg);
rc = -EINVAL;
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index b8e08cb67a18..9b3cac0abecc 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -33,6 +33,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/acpi.h>
+#include <linux/acpi_io.h>
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/timer.h>
@@ -45,8 +46,9 @@
#include <linux/irq_work.h>
#include <linux/llist.h>
#include <linux/genalloc.h>
+#include <linux/pci.h>
+#include <linux/aer.h>
#include <acpi/apei.h>
-#include <acpi/atomicio.h>
#include <acpi/hed.h>
#include <asm/mce.h>
#include <asm/tlbflush.h>
@@ -118,7 +120,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;
@@ -299,7 +301,7 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic)
if (!ghes)
return ERR_PTR(-ENOMEM);
ghes->generic = generic;
- rc = acpi_pre_map_gar(&generic->error_status_address);
+ rc = acpi_os_map_generic_address(&generic->error_status_address);
if (rc)
goto err_free;
error_block_length = generic->error_block_length;
@@ -319,7 +321,7 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic)
return ghes;
err_unmap:
- acpi_post_unmap_gar(&generic->error_status_address);
+ acpi_os_unmap_generic_address(&generic->error_status_address);
err_free:
kfree(ghes);
return ERR_PTR(rc);
@@ -328,7 +330,7 @@ err_free:
static void ghes_fini(struct ghes *ghes)
{
kfree(ghes->estatus);
- acpi_post_unmap_gar(&ghes->generic->error_status_address);
+ acpi_os_unmap_generic_address(&ghes->generic->error_status_address);
}
enum {
@@ -399,7 +401,7 @@ static int ghes_read_estatus(struct ghes *ghes, int silent)
u32 len;
int rc;
- rc = acpi_atomic_read(&buf_paddr, &g->error_status_address);
+ rc = apei_read(&buf_paddr, &g->error_status_address);
if (rc) {
if (!silent && printk_ratelimit())
pr_warning(FW_WARN GHES_PFX
@@ -476,6 +478,27 @@ static void ghes_do_proc(const struct acpi_hest_generic_status *estatus)
}
#endif
}
+#ifdef CONFIG_ACPI_APEI_PCIEAER
+ else if (!uuid_le_cmp(*(uuid_le *)gdata->section_type,
+ CPER_SEC_PCIE)) {
+ struct cper_sec_pcie *pcie_err;
+ pcie_err = (struct cper_sec_pcie *)(gdata+1);
+ if (sev == GHES_SEV_RECOVERABLE &&
+ sec_sev == GHES_SEV_RECOVERABLE &&
+ pcie_err->validation_bits & CPER_PCIE_VALID_DEVICE_ID &&
+ pcie_err->validation_bits & CPER_PCIE_VALID_AER_INFO) {
+ unsigned int devfn;
+ int aer_severity;
+ devfn = PCI_DEVFN(pcie_err->device_id.device,
+ pcie_err->device_id.function);
+ aer_severity = cper_severity_to_aer(sev);
+ aer_recover_queue(pcie_err->device_id.segment,
+ pcie_err->device_id.bus,
+ devfn, aer_severity);
+ }
+
+ }
+#endif
}
}
@@ -483,16 +506,22 @@ static void __ghes_print_estatus(const char *pfx,
const struct acpi_hest_generic *generic,
const struct acpi_hest_generic_status *estatus)
{
+ static atomic_t seqno;
+ unsigned int curr_seqno;
+ char pfx_seq[64];
+
if (pfx == NULL) {
if (ghes_severity(estatus->error_severity) <=
GHES_SEV_CORRECTED)
- pfx = KERN_WARNING HW_ERR;
+ pfx = KERN_WARNING;
else
- pfx = KERN_ERR HW_ERR;
+ pfx = KERN_ERR;
}
+ curr_seqno = atomic_inc_return(&seqno);
+ snprintf(pfx_seq, sizeof(pfx_seq), "%s{%u}" HW_ERR, pfx, curr_seqno);
printk("%s""Hardware error from APEI Generic Hardware Error Source: %d\n",
- pfx, generic->header.source_id);
- apei_estatus_print(pfx, estatus);
+ pfx_seq, generic->header.source_id);
+ apei_estatus_print(pfx_seq, estatus);
}
static int ghes_print_estatus(const char *pfx,
@@ -711,26 +740,34 @@ static int ghes_notify_sci(struct notifier_block *this,
return ret;
}
+static struct llist_node *llist_nodes_reverse(struct llist_node *llnode)
+{
+ struct llist_node *next, *tail = NULL;
+
+ while (llnode) {
+ next = llnode->next;
+ llnode->next = tail;
+ tail = llnode;
+ llnode = next;
+ }
+
+ return tail;
+}
+
static void ghes_proc_in_irq(struct irq_work *irq_work)
{
- struct llist_node *llnode, *next, *tail = NULL;
+ struct llist_node *llnode, *next;
struct ghes_estatus_node *estatus_node;
struct acpi_hest_generic *generic;
struct acpi_hest_generic_status *estatus;
u32 len, node_len;
+ llnode = llist_del_all(&ghes_estatus_llist);
/*
* Because the time order of estatus in list is reversed,
* revert it back to proper order.
*/
- llnode = llist_del_all(&ghes_estatus_llist);
- while (llnode) {
- next = llnode->next;
- llnode->next = tail;
- tail = llnode;
- llnode = next;
- }
- llnode = tail;
+ llnode = llist_nodes_reverse(llnode);
while (llnode) {
next = llnode->next;
estatus_node = llist_entry(llnode, struct ghes_estatus_node,
@@ -750,6 +787,32 @@ static void ghes_proc_in_irq(struct irq_work *irq_work)
}
}
+static void ghes_print_queued_estatus(void)
+{
+ struct llist_node *llnode;
+ struct ghes_estatus_node *estatus_node;
+ struct acpi_hest_generic *generic;
+ struct acpi_hest_generic_status *estatus;
+ u32 len, node_len;
+
+ llnode = llist_del_all(&ghes_estatus_llist);
+ /*
+ * Because the time order of estatus in list is reversed,
+ * revert it back to proper order.
+ */
+ llnode = llist_nodes_reverse(llnode);
+ while (llnode) {
+ estatus_node = llist_entry(llnode, struct ghes_estatus_node,
+ llnode);
+ estatus = GHES_ESTATUS_FROM_NODE(estatus_node);
+ len = apei_estatus_len(estatus);
+ node_len = GHES_ESTATUS_NODE_LEN(len);
+ generic = estatus_node->generic;
+ ghes_print_estatus(NULL, generic, estatus);
+ llnode = llnode->next;
+ }
+}
+
static int ghes_notify_nmi(unsigned int cmd, struct pt_regs *regs)
{
struct ghes *ghes, *ghes_global = NULL;
@@ -775,7 +838,8 @@ static int ghes_notify_nmi(unsigned int cmd, struct pt_regs *regs)
if (sev_global >= GHES_SEV_PANIC) {
oops_begin();
- __ghes_print_estatus(KERN_EMERG HW_ERR, ghes_global->generic,
+ ghes_print_queued_estatus();
+ __ghes_print_estatus(KERN_EMERG, ghes_global->generic,
ghes_global->estatus);
/* reboot to log the error! */
if (panic_timeout == 0)
diff --git a/drivers/acpi/apei/hest.c b/drivers/acpi/apei/hest.c
index 05fee06f4d6e..7f00cf38098f 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 */
@@ -221,10 +221,9 @@ void __init acpi_hest_init(void)
status = acpi_get_table(ACPI_SIG_HEST, 0,
(struct acpi_table_header **)&hest_tab);
- if (status == AE_NOT_FOUND) {
- pr_info(HEST_PFX "Table not found.\n");
+ if (status == AE_NOT_FOUND)
goto err;
- } else if (ACPI_FAILURE(status)) {
+ else if (ACPI_FAILURE(status)) {
const char *msg = acpi_format_exception(status);
pr_err(HEST_PFX "Failed to get table, %s\n", msg);
rc = -EINVAL;
diff --git a/drivers/acpi/atomicio.c b/drivers/acpi/atomicio.c
index cfc0cc10af39..d4a5b3d3657b 100644
--- a/drivers/acpi/atomicio.c
+++ b/drivers/acpi/atomicio.c
@@ -32,6 +32,8 @@
#include <linux/rculist.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
#include <acpi/atomicio.h>
#define ACPI_PFX "ACPI: "
@@ -97,6 +99,37 @@ static void __iomem *__acpi_try_ioremap(phys_addr_t paddr,
return NULL;
}
+#ifndef CONFIG_IA64
+#define should_use_kmap(pfn) page_is_ram(pfn)
+#else
+/* ioremap will take care of cache attributes */
+#define should_use_kmap(pfn) 0
+#endif
+
+static void __iomem *acpi_map(phys_addr_t pg_off, unsigned long pg_sz)
+{
+ unsigned long pfn;
+
+ pfn = pg_off >> PAGE_SHIFT;
+ if (should_use_kmap(pfn)) {
+ if (pg_sz > PAGE_SIZE)
+ return NULL;
+ return (void __iomem __force *)kmap(pfn_to_page(pfn));
+ } else
+ return ioremap(pg_off, pg_sz);
+}
+
+static void acpi_unmap(phys_addr_t pg_off, void __iomem *vaddr)
+{
+ unsigned long pfn;
+
+ pfn = pg_off >> PAGE_SHIFT;
+ if (page_is_ram(pfn))
+ kunmap(pfn_to_page(pfn));
+ else
+ iounmap(vaddr);
+}
+
/*
* Used to pre-map the specified IO memory area. First try to find
* whether the area is already pre-mapped, if it is, increase the
@@ -119,7 +152,7 @@ static void __iomem *acpi_pre_map(phys_addr_t paddr,
pg_off = paddr & PAGE_MASK;
pg_sz = ((paddr + size + PAGE_SIZE - 1) & PAGE_MASK) - pg_off;
- vaddr = ioremap(pg_off, pg_sz);
+ vaddr = acpi_map(pg_off, pg_sz);
if (!vaddr)
return NULL;
map = kmalloc(sizeof(*map), GFP_KERNEL);
@@ -135,7 +168,7 @@ static void __iomem *acpi_pre_map(phys_addr_t paddr,
vaddr = __acpi_try_ioremap(paddr, size);
if (vaddr) {
spin_unlock_irqrestore(&acpi_iomaps_lock, flags);
- iounmap(map->vaddr);
+ acpi_unmap(pg_off, map->vaddr);
kfree(map);
return vaddr;
}
@@ -144,7 +177,7 @@ static void __iomem *acpi_pre_map(phys_addr_t paddr,
return map->vaddr + (paddr - map->paddr);
err_unmap:
- iounmap(vaddr);
+ acpi_unmap(pg_off, vaddr);
return NULL;
}
@@ -177,7 +210,7 @@ static void acpi_post_unmap(phys_addr_t paddr, unsigned long size)
return;
synchronize_rcu();
- iounmap(map->vaddr);
+ acpi_unmap(map->paddr, map->vaddr);
kfree(map);
}
@@ -260,6 +293,21 @@ int acpi_post_unmap_gar(struct acpi_generic_address *reg)
}
EXPORT_SYMBOL_GPL(acpi_post_unmap_gar);
+#ifdef readq
+static inline u64 read64(const volatile void __iomem *addr)
+{
+ return readq(addr);
+}
+#else
+static inline u64 read64(const volatile void __iomem *addr)
+{
+ u64 l, h;
+ l = readl(addr);
+ h = readl(addr+4);
+ return l | (h << 32);
+}
+#endif
+
/*
* Can be used in atomic (including NMI) or process context. RCU read
* lock can only be released after the IO memory area accessing.
@@ -280,11 +328,9 @@ static int acpi_atomic_read_mem(u64 paddr, u64 *val, u32 width)
case 32:
*val = readl(addr);
break;
-#ifdef readq
case 64:
- *val = readq(addr);
+ *val = read64(addr);
break;
-#endif
default:
return -EINVAL;
}
@@ -293,6 +339,19 @@ static int acpi_atomic_read_mem(u64 paddr, u64 *val, u32 width)
return 0;
}
+#ifdef writeq
+static inline void write64(u64 val, volatile void __iomem *addr)
+{
+ writeq(val, addr);
+}
+#else
+static inline void write64(u64 val, volatile void __iomem *addr)
+{
+ writel(val, addr);
+ writel(val>>32, addr+4);
+}
+#endif
+
static int acpi_atomic_write_mem(u64 paddr, u64 val, u32 width)
{
void __iomem *addr;
@@ -309,11 +368,9 @@ static int acpi_atomic_write_mem(u64 paddr, u64 val, u32 width)
case 32:
writel(val, addr);
break;
-#ifdef writeq
case 64:
- writeq(val, addr);
+ write64(val, addr);
break;
-#endif
default:
return -EINVAL;
}
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 19a61136d848..88eb14304667 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/numa.c b/drivers/acpi/numa.c
index 3b5c3189fd99..e56f3be7b07d 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -45,6 +45,8 @@ static int pxm_to_node_map[MAX_PXM_DOMAINS]
static int node_to_pxm_map[MAX_NUMNODES]
= { [0 ... MAX_NUMNODES - 1] = PXM_INVAL };
+unsigned char acpi_srat_revision __initdata;
+
int pxm_to_node(int pxm)
{
if (pxm < 0)
@@ -255,9 +257,13 @@ acpi_parse_memory_affinity(struct acpi_subtable_header * header,
static int __init acpi_parse_srat(struct acpi_table_header *table)
{
+ struct acpi_table_srat *srat;
if (!table)
return -EINVAL;
+ srat = (struct acpi_table_srat *)table;
+ acpi_srat_revision = srat->header.revision;
+
/* Real work done in acpi_table_parse_srat below. */
return 0;
diff --git a/drivers/acpi/nvs.c b/drivers/acpi/nvs.c
index 096787b43c96..7a2035fa8c71 100644
--- a/drivers/acpi/nvs.c
+++ b/drivers/acpi/nvs.c
@@ -15,6 +15,56 @@
#include <linux/acpi_io.h>
#include <acpi/acpiosxf.h>
+/* ACPI NVS regions, APEI may use it */
+
+struct nvs_region {
+ __u64 phys_start;
+ __u64 size;
+ struct list_head node;
+};
+
+static LIST_HEAD(nvs_region_list);
+
+#ifdef CONFIG_ACPI_SLEEP
+static int suspend_nvs_register(unsigned long start, unsigned long size);
+#else
+static inline int suspend_nvs_register(unsigned long a, unsigned long b)
+{
+ return 0;
+}
+#endif
+
+int acpi_nvs_register(__u64 start, __u64 size)
+{
+ struct nvs_region *region;
+
+ region = kmalloc(sizeof(*region), GFP_KERNEL);
+ if (!region)
+ return -ENOMEM;
+ region->phys_start = start;
+ region->size = size;
+ list_add_tail(&region->node, &nvs_region_list);
+
+ return suspend_nvs_register(start, size);
+}
+
+int acpi_nvs_for_each_region(int (*func)(__u64 start, __u64 size, void *data),
+ void *data)
+{
+ int rc;
+ struct nvs_region *region;
+
+ list_for_each_entry(region, &nvs_region_list, node) {
+ rc = func(region->phys_start, region->size, data);
+ if (rc)
+ return rc;
+ }
+
+ return 0;
+}
+
+
+#ifdef CONFIG_ACPI_SLEEP
/*
* Platforms, like ACPI, may want us to save some memory used by them during
* suspend and to restore the contents of this memory during the subsequent
@@ -41,7 +91,7 @@ static LIST_HEAD(nvs_list);
* things so that the data from page-aligned addresses in this region will
* be copied into separate RAM pages.
*/
-int suspend_nvs_register(unsigned long start, unsigned long size)
+static int suspend_nvs_register(unsigned long start, unsigned long size)
{
struct nvs_page *entry, *next;
@@ -159,3 +209,4 @@ void suspend_nvs_restore(void)
if (entry->data)
memcpy(entry->kaddr, entry->data, entry->size);
}
+#endif
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index f31c5c5f1b7e..fcc12d842bcc 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -83,19 +83,6 @@ static struct workqueue_struct *kacpi_notify_wq;
struct workqueue_struct *kacpi_hotplug_wq;
EXPORT_SYMBOL(kacpi_hotplug_wq);
-struct acpi_res_list {
- resource_size_t start;
- resource_size_t end;
- acpi_adr_space_type resource_type; /* IO port, System memory, ...*/
- char name[5]; /* only can have a length of 4 chars, make use of this
- one instead of res->name, no need to kalloc then */
- struct list_head resource_list;
- int count;
-};
-
-static LIST_HEAD(resource_list_head);
-static DEFINE_SPINLOCK(acpi_res_lock);
-
/*
* This list of permanent mappings is for memory that may be accessed from
* interrupt context, where we can't do the ioremap().
@@ -166,17 +153,21 @@ static u32 acpi_osi_handler(acpi_string interface, u32 supported)
return supported;
}
-static void __init acpi_request_region (struct acpi_generic_address *addr,
+static void __init acpi_request_region (struct acpi_generic_address *gas,
unsigned int length, char *desc)
{
- if (!addr->address || !length)
+ u64 addr;
+
+ /* Handle possible alignment issues */
+ memcpy(&addr, &gas->address, sizeof(addr));
+ if (!addr || !length)
return;
/* Resources are never freed */
- if (addr->space_id == ACPI_ADR_SPACE_SYSTEM_IO)
- request_region(addr->address, length, desc);
- else if (addr->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
- request_mem_region(addr->address, length, desc);
+ if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO)
+ request_region(addr, length, desc);
+ else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
+ request_mem_region(addr, length, desc);
}
static int __init acpi_reserve_resources(void)
@@ -427,35 +418,42 @@ void __init early_acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
__acpi_unmap_table(virt, size);
}
-static int acpi_os_map_generic_address(struct acpi_generic_address *addr)
+int acpi_os_map_generic_address(struct acpi_generic_address *gas)
{
+ u64 addr;
void __iomem *virt;
- if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
+ if (gas->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
return 0;
- if (!addr->address || !addr->bit_width)
+ /* Handle possible alignment issues */
+ memcpy(&addr, &gas->address, sizeof(addr));
+ if (!addr || !gas->bit_width)
return -EINVAL;
- virt = acpi_os_map_memory(addr->address, addr->bit_width / 8);
+ virt = acpi_os_map_memory(addr, gas->bit_width / 8);
if (!virt)
return -EIO;
return 0;
}
+EXPORT_SYMBOL(acpi_os_map_generic_address);
-static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr)
+void acpi_os_unmap_generic_address(struct acpi_generic_address *gas)
{
+ u64 addr;
struct acpi_ioremap *map;
- if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
+ if (gas->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
return;
- if (!addr->address || !addr->bit_width)
+ /* Handle possible alignment issues */
+ memcpy(&addr, &gas->address, sizeof(addr));
+ if (!addr || !gas->bit_width)
return;
mutex_lock(&acpi_ioremap_lock);
- map = acpi_map_lookup(addr->address, addr->bit_width / 8);
+ map = acpi_map_lookup(addr, gas->bit_width / 8);
if (!map) {
mutex_unlock(&acpi_ioremap_lock);
return;
@@ -465,6 +463,7 @@ static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr)
acpi_os_map_cleanup(map);
}
+EXPORT_SYMBOL(acpi_os_unmap_generic_address);
#ifdef ACPI_FUTURE_USAGE
acpi_status
@@ -1278,44 +1277,28 @@ __setup("acpi_enforce_resources=", acpi_enforce_resources_setup);
* drivers */
int acpi_check_resource_conflict(const struct resource *res)
{
- struct acpi_res_list *res_list_elem;
- int ioport = 0, clash = 0;
+ acpi_adr_space_type space_id;
+ acpi_size length;
+ u8 warn = 0;
+ int clash = 0;
if (acpi_enforce_resources == ENFORCE_RESOURCES_NO)
return 0;
if (!(res->flags & IORESOURCE_IO) && !(res->flags & IORESOURCE_MEM))
return 0;
- ioport = res->flags & IORESOURCE_IO;
-
- spin_lock(&acpi_res_lock);
- list_for_each_entry(res_list_elem, &resource_list_head,
- resource_list) {
- if (ioport && (res_list_elem->resource_type
- != ACPI_ADR_SPACE_SYSTEM_IO))
- continue;
- if (!ioport && (res_list_elem->resource_type
- != ACPI_ADR_SPACE_SYSTEM_MEMORY))
- continue;
+ if (res->flags & IORESOURCE_IO)
+ space_id = ACPI_ADR_SPACE_SYSTEM_IO;
+ else
+ space_id = ACPI_ADR_SPACE_SYSTEM_MEMORY;
- if (res->end < res_list_elem->start
- || res_list_elem->end < res->start)
- continue;
- clash = 1;
- break;
- }
- spin_unlock(&acpi_res_lock);
+ length = res->end - res->start + 1;
+ if (acpi_enforce_resources != ENFORCE_RESOURCES_NO)
+ warn = 1;
+ clash = acpi_check_address_range(space_id, res->start, length, warn);
if (clash) {
if (acpi_enforce_resources != ENFORCE_RESOURCES_NO) {
- printk(KERN_WARNING "ACPI: resource %s %pR"
- " conflicts with ACPI region %s "
- "[%s 0x%zx-0x%zx]\n",
- res->name, res, res_list_elem->name,
- (res_list_elem->resource_type ==
- ACPI_ADR_SPACE_SYSTEM_IO) ? "io" : "mem",
- (size_t) res_list_elem->start,
- (size_t) res_list_elem->end);
if (acpi_enforce_resources == ENFORCE_RESOURCES_LAX)
printk(KERN_NOTICE "ACPI: This conflict may"
" cause random problems and system"
@@ -1467,155 +1450,6 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object)
kmem_cache_free(cache, object);
return (AE_OK);
}
-
-static inline int acpi_res_list_add(struct acpi_res_list *res)
-{
- struct acpi_res_list *res_list_elem;
-
- list_for_each_entry(res_list_elem, &resource_list_head,
- resource_list) {
-
- if (res->resource_type == res_list_elem->resource_type &&
- res->start == res_list_elem->start &&
- res->end == res_list_elem->end) {
-
- /*
- * The Region(addr,len) already exist in the list,
- * just increase the count
- */
-
- res_list_elem->count++;
- return 0;
- }
- }
-
- res->count = 1;
- list_add(&res->resource_list, &resource_list_head);
- return 1;
-}
-
-static inline void acpi_res_list_del(struct acpi_res_list *res)
-{
- struct acpi_res_list *res_list_elem;
-
- list_for_each_entry(res_list_elem, &resource_list_head,
- resource_list) {
-
- if (res->resource_type == res_list_elem->resource_type &&
- res->start == res_list_elem->start &&
- res->end == res_list_elem->end) {
-
- /*
- * If the res count is decreased to 0,
- * remove and free it
- */
-
- if (--res_list_elem->count == 0) {
- list_del(&res_list_elem->resource_list);
- kfree(res_list_elem);
- }
- return;
- }
- }
-}
-
-acpi_status
-acpi_os_invalidate_address(
- u8 space_id,
- acpi_physical_address address,
- acpi_size length)
-{
- struct acpi_res_list res;
-
- switch (space_id) {
- case ACPI_ADR_SPACE_SYSTEM_IO:
- case ACPI_ADR_SPACE_SYSTEM_MEMORY:
- /* Only interference checks against SystemIO and SystemMemory
- are needed */
- res.start = address;
- res.end = address + length - 1;
- res.resource_type = space_id;
- spin_lock(&acpi_res_lock);
- acpi_res_list_del(&res);
- spin_unlock(&acpi_res_lock);
- break;
- case ACPI_ADR_SPACE_PCI_CONFIG:
- case ACPI_ADR_SPACE_EC:
- case ACPI_ADR_SPACE_SMBUS:
- case ACPI_ADR_SPACE_CMOS:
- case ACPI_ADR_SPACE_PCI_BAR_TARGET:
- case ACPI_ADR_SPACE_DATA_TABLE:
- case ACPI_ADR_SPACE_FIXED_HARDWARE:
- break;
- }
- return AE_OK;
-}
-
-/******************************************************************************
- *
- * FUNCTION: acpi_os_validate_address
- *
- * PARAMETERS: space_id - ACPI space ID
- * address - Physical address
- * length - Address length
- *
- * RETURN: AE_OK if address/length is valid for the space_id. Otherwise,
- * should return AE_AML_ILLEGAL_ADDRESS.
- *
- * DESCRIPTION: Validate a system address via the host OS. Used to validate
- * the addresses accessed by AML operation regions.
- *
- *****************************************************************************/
-
-acpi_status
-acpi_os_validate_address (
- u8 space_id,
- acpi_physical_address address,
- acpi_size length,
- char *name)
-{
- struct acpi_res_list *res;
- int added;
- if (acpi_enforce_resources == ENFORCE_RESOURCES_NO)
- return AE_OK;
-
- switch (space_id) {
- case ACPI_ADR_SPACE_SYSTEM_IO:
- case ACPI_ADR_SPACE_SYSTEM_MEMORY:
- /* Only interference checks against SystemIO and SystemMemory
- are needed */
- res = kzalloc(sizeof(struct acpi_res_list), GFP_KERNEL);
- if (!res)
- return AE_OK;
- /* ACPI names are fixed to 4 bytes, still better use strlcpy */
- strlcpy(res->name, name, 5);
- res->start = address;
- res->end = address + length - 1;
- res->resource_type = space_id;
- spin_lock(&acpi_res_lock);
- added = acpi_res_list_add(res);
- spin_unlock(&acpi_res_lock);
- pr_debug("%s %s resource: start: 0x%llx, end: 0x%llx, "
- "name: %s\n", added ? "Added" : "Already exist",
- (space_id == ACPI_ADR_SPACE_SYSTEM_IO)
- ? "SystemIO" : "System Memory",
- (unsigned long long)res->start,
- (unsigned long long)res->end,
- res->name);
- if (!added)
- kfree(res);
- break;
- case ACPI_ADR_SPACE_PCI_CONFIG:
- case ACPI_ADR_SPACE_EC:
- case ACPI_ADR_SPACE_SMBUS:
- case ACPI_ADR_SPACE_CMOS:
- case ACPI_ADR_SPACE_PCI_BAR_TARGET:
- case ACPI_ADR_SPACE_DATA_TABLE:
- case ACPI_ADR_SPACE_FIXED_HARDWARE:
- break;
- }
- return AE_OK;
-}
#endif
acpi_status __init acpi_os_initialize(void)
diff --git a/drivers/acpi/pci_slot.c b/drivers/acpi/pci_slot.c
index 07f7fea8a4e2..e50e31a518af 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/processor_core.c b/drivers/acpi/processor_core.c
index 3a0428e8435c..c850de4c9a14 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -173,8 +173,30 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
apic_id = map_mat_entry(handle, type, acpi_id);
if (apic_id == -1)
apic_id = map_madt_entry(type, acpi_id);
- if (apic_id == -1)
- return apic_id;
+ if (apic_id == -1) {
+ /*
+ * On UP processor, there is no _MAT or MADT table.
+ * So above apic_id is always set to -1.
+ *
+ * BIOS may define multiple CPU handles even for UP processor.
+ * For example,
+ *
+ * Scope (_PR)
+ * {
+ * Processor (CPU0, 0x00, 0x00000410, 0x06) {}
+ * Processor (CPU1, 0x01, 0x00000410, 0x06) {}
+ * Processor (CPU2, 0x02, 0x00000410, 0x06) {}
+ * Processor (CPU3, 0x03, 0x00000410, 0x06) {}
+ * }
+ *
+ * Ignores apic_id and always return 0 for CPU0's handle.
+ * Return -1 for other CPU's handle.
+ */
+ if (acpi_id == 0)
+ return acpi_id;
+ else
+ return apic_id;
+ }
#ifdef CONFIG_SMP
for_each_possible_cpu(i) {
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index 20a68ca386de..0034ede38710 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -82,7 +82,7 @@ MODULE_LICENSE("GPL");
static int acpi_processor_add(struct acpi_device *device);
static int acpi_processor_remove(struct acpi_device *device, int type);
static void acpi_processor_notify(struct acpi_device *device, u32 event);
-static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu);
+static acpi_status acpi_processor_hotadd_init(struct acpi_processor *pr);
static int acpi_processor_handle_eject(struct acpi_processor *pr);
@@ -324,10 +324,8 @@ static int acpi_processor_get_info(struct acpi_device *device)
* they are physically not present.
*/
if (pr->id == -1) {
- if (ACPI_FAILURE
- (acpi_processor_hotadd_init(pr->handle, &pr->id))) {
+ if (ACPI_FAILURE(acpi_processor_hotadd_init(pr)))
return -ENODEV;
- }
}
/*
* On some boxes several processors use the same processor bus id.
@@ -539,6 +537,7 @@ err_thermal_unregister:
thermal_cooling_device_unregister(pr->cdev);
err_power_exit:
acpi_processor_power_exit(pr, device);
+ sysfs_remove_link(&device->dev.kobj, "sysdev");
err_free_cpumask:
free_cpumask_var(pr->throttling.shared_cpu_map);
@@ -720,18 +719,19 @@ processor_walk_namespace_cb(acpi_handle handle,
return (AE_OK);
}
-static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu)
+static acpi_status acpi_processor_hotadd_init(struct acpi_processor *pr)
{
+ acpi_handle handle = pr->handle;
if (!is_processor_present(handle)) {
return AE_ERROR;
}
- if (acpi_map_lsapic(handle, p_cpu))
+ if (acpi_map_lsapic(handle, &pr->id))
return AE_ERROR;
- if (arch_register_cpu(*p_cpu)) {
- acpi_unmap_lsapic(*p_cpu);
+ if (arch_register_cpu(pr->id)) {
+ acpi_unmap_lsapic(pr->id);
return AE_ERROR;
}
@@ -748,7 +748,7 @@ static int acpi_processor_handle_eject(struct acpi_processor *pr)
return (0);
}
#else
-static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu)
+static acpi_status acpi_processor_hotadd_init(struct acpi_processor *pr)
{
return AE_ERROR;
}
@@ -827,8 +827,6 @@ static void __exit acpi_processor_exit(void)
acpi_bus_unregister_driver(&acpi_processor_driver);
- cpuidle_unregister_driver(&acpi_idle_driver);
-
return;
}
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 08a44b532f7c..eaef02afc7cf 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 69ac373c72ab..fdf27b9fce43 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 11c9aea4f4f7..c06e0ec11556 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 9a7f0ea565df..74aaee30e264 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 d6a4677fdf71..1e65842e2ca7 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 5a2c95ba050a..0120b0d1e9a5 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 e0bc9646a38e..55d6179dde58 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 1e9140626a83..e7e610aa9a7a 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 9a51df4f5b74..b182c2f7d777 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 fcbec8ac134d..7be9f79018e9 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -179,7 +179,7 @@ config GENERIC_CPU_DEVICES
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/bus.c b/drivers/base/bus.c
index 99dc5921e1dd..40fb12288ce2 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -915,9 +915,10 @@ static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store);
/**
* __bus_register - register a driver-core subsystem
- * @bus: bus.
+ * @bus: bus to register
+ * @key: lockdep class key
*
- * Once we have that, we registered the bus with the kobject
+ * Once we have that, we register the bus with the kobject
* infrastructure, then register the children subsystems it has:
* the devices and drivers that belong to the subsystem.
*/
@@ -1220,8 +1221,8 @@ static void system_root_device_release(struct device *dev)
}
/**
* subsys_system_register - register a subsystem at /sys/devices/system/
- * @subsys - system subsystem
- * @groups - default attributes for the root device
+ * @subsys: system subsystem
+ * @groups: default attributes for the root device
*
* All 'system' subsystems have a /sys/devices/system/<name> root device
* with the name of the subsystem. The root device can carry subsystem-
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 26ab358dac62..6c9387d646ec 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -525,8 +525,7 @@ static int _request_firmware(const struct firmware **firmware_p,
if (!firmware) {
dev_err(device, "%s: kmalloc(struct firmware) failed\n",
__func__);
- retval = -ENOMEM;
- goto out;
+ return -ENOMEM;
}
if (fw_get_builtin_firmware(firmware, name)) {
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 92e6a9048065..978bbf7ac6af 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 51527ee92d10..66a265bf5867 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/main.c b/drivers/bcma/main.c
index bcd1c01cde9e..b8379b90d045 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -179,10 +179,8 @@ int __devinit bcma_bus_register(struct bcma_bus *bus)
err = bcma_sprom_get(bus);
if (err == -ENOENT) {
pr_err("No SPROM available\n");
- } else if (err) {
+ } else if (err)
pr_err("Failed to get SPROM: %d\n", err);
- return -ENOENT;
- }
/* Register found cores */
bcma_register_cores(bus);
diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c
index 6621b2221b40..f94cccccfa56 100644
--- a/drivers/bcma/scan.c
+++ b/drivers/bcma/scan.c
@@ -415,15 +415,18 @@ int bcma_bus_scan(struct bcma_bus *bus)
core->bus = bus;
err = bcma_get_next_core(bus, &eromptr, NULL, core_num, core);
- if (err == -ENODEV) {
- core_num++;
- continue;
- } else if (err == -ENXIO)
- continue;
- else if (err == -ESPIPE)
- break;
- else if (err < 0)
+ if (err < 0) {
+ kfree(core);
+ if (err == -ENODEV) {
+ core_num++;
+ continue;
+ } else if (err == -ENXIO) {
+ continue;
+ } else if (err == -ESPIPE) {
+ break;
+ }
return err;
+ }
core->core_index = core_num++;
bus->nr_cores++;
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 6f07ec1c2f58..4e4c8a4a5fd3 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 76646e9a1c91..5b795059f8fb 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 587cce57adae..b0f553b26d0f 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 9cf20355ceec..8d680562ba73 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 0358e55356c8..211fc44f84be 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 000000000000..b5dd14e072f2
--- /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 000000000000..4fbef8c8329b
--- /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 000000000000..b74eab70c3d0
--- /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 000000000000..723d7c4946dc
--- /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 000000000000..c1dc4d86c221
--- /dev/null
+++ b/drivers/block/nvme.c
@@ -0,0 +1,1739 @@
+/*
+ * 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;
+}
+
+static void 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);
+}
+
+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 ad124525ac23..ec64e7f5d1ce 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 46b8136c31bb..ba2b6b5e5910 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 869e7676d46f..831e3ac156e6 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 f21b520ef419..ec8f9ed6326e 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 a79fb4f7ff62..4a27b1de5fcb 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 7179f79d7468..2596042eb987 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 148ab944378d..3fd31dec8c9c 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 b70f0fca9a42..e7472f567c9d 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 0e376d46bdd1..7333b9e44411 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 ffd5ca919295..c4a60badf252 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -250,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 */
diff --git a/drivers/block/xd.c b/drivers/block/xd.c
index 4abd2bcd20fb..51a972704db5 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 15ec4db194d1..0088bf60f368 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 dfb1b3a43a5d..d0ee7edc9be8 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 37c794d31264..24a2fb57e5d0 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 9fd3ee203b1e..2f22874c0a37 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/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 066d5ec83a9b..e61a195969bf 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 8bf0c3e774e8..661a8dc4d2f8 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 01c23dfe2a10..c2d637adb3ca 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 2118211aff99..55eaf474d32c 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 780498d76581..444f8b6ab411 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 29aacd81de78..08704ae53956 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/i8k.c b/drivers/char/i8k.c
index 6e40072fbf67..40cc0cf2ded6 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 9397ab49b72e..50fcf9c04569 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 97c3edb95ae7..f43485607063 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 a12f52400dbc..bf586ae1ee83 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 15781396af25..07f6a5abe372 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/random.c b/drivers/char/random.c
index 85da8740586b..54ca8b23cde3 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/tpm.c b/drivers/char/tpm/tpm.c
index 6a8771f47a55..32362cf35b8d 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -846,6 +846,15 @@ int tpm_do_selftest(struct tpm_chip *chip)
do {
rc = __tpm_pcr_read(chip, 0, digest);
+ if (rc == TPM_ERR_DISABLED || rc == TPM_ERR_DEACTIVATED) {
+ dev_info(chip->dev,
+ "TPM is disabled/deactivated (0x%X)\n", rc);
+ /* TPM is disabled and/or deactivated; driver can
+ * proceed and TPM does handle commands for
+ * suspend/resume correctly
+ */
+ return 0;
+ }
if (rc != TPM_WARN_DOING_SELFTEST)
return rc;
msleep(delay_msec);
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 8c1df302fbb6..010547138281 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -39,6 +39,9 @@ enum tpm_addr {
};
#define TPM_WARN_DOING_SELFTEST 0x802
+#define TPM_ERR_DEACTIVATED 0x6
+#define TPM_ERR_DISABLED 0x7
+
#define TPM_HEADER_SIZE 10
extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr,
char *);
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index 10cc44ceb5d1..a1748621111b 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -255,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)");
@@ -500,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");
@@ -828,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/dma/Kconfig b/drivers/dma/Kconfig
index 5a99bb3f255a..f1a274994bb1 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 30cf3b1f0c5c..009a222e8283 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 0698695e8bf9..8a281584458b 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 fcfa0a8b5c59..97f87b29b9f3 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 aa4c9aebab7c..dcaedfc181cf 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 4234f416ef11..d65a718c0f9b 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 9f7e0e6a7eea..6c0e2d4c6682 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 7a5c80990e9e..abff3714fdda 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 b48967b499da..a6c6051ec858 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 9bfd6d360718..9b592b02b5f4 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 c3419518d701..5eef6946a367 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 b47e2b803faf..59e7a965772b 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 8a781540590c..b98070c33ca9 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 4be55f9bb6c1..e4383ee2c9ac 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 f993955a640c..a8af379680c1 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 19a0c64d45d3..74f70aadf9e4 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 aea5ee88ce03..c83d35b97bd8 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 e03f811a83dd..04be90b645b8 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 0e5ef33f90a1..6212b16e8cf2 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 8ba4edc6185e..4d6d4cf66949 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 fc903c0ed234..b06cd4ca626f 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 a6d0e3dbed07..823f58179f9d 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 09adcfcd953e..b8ec03ee8e22 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 81809c2b46ab..54043cd831c8 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 000000000000..2333810d1688
--- /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 13259cad0ceb..cc5ecbc067a3 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 b44c455158de..8d3d490968a3 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 a4a398f2ef61..a6f9c1684a0f 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 cbd83e362b5e..6122c364cf11 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 b153674431f1..e294e1b3616c 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 68375bc3aef6..80e95aa3bf14 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/gpio/Kconfig b/drivers/gpio/Kconfig
index 573532f7553e..d0c41188d4e5 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -87,6 +87,7 @@ config GPIO_GENERIC_PLATFORM
config GPIO_IT8761E
tristate "IT8761E GPIO support"
+ depends on X86 # unconditional access to IO space.
help
Say yes here to support GPIO functionality of IT8761E super I/O chip.
@@ -138,6 +139,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 62e641e79e8f..fa10df604c01 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 000000000000..3dd29399cef5
--- /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-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c
index 461958fc2264..03d6dd5dcb77 100644
--- a/drivers/gpio/gpio-ml-ioh.c
+++ b/drivers/gpio/gpio-ml-ioh.c
@@ -248,7 +248,7 @@ static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port)
static int ioh_irq_type(struct irq_data *d, unsigned int type)
{
u32 im;
- u32 *im_reg;
+ void __iomem *im_reg;
u32 ien;
u32 im_pos;
int ch;
@@ -412,7 +412,7 @@ static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
int i, j;
struct ioh_gpio *chip;
void __iomem *base;
- void __iomem *chip_save;
+ void *chip_save;
int irq_base;
ret = pci_enable_device(pdev);
@@ -428,7 +428,7 @@ static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
}
base = pci_iomap(pdev, 1, 0);
- if (base == 0) {
+ if (!base) {
dev_err(&pdev->dev, "%s : pci_iomap failed", __func__);
ret = -ENOMEM;
goto err_iomap;
@@ -521,7 +521,7 @@ static void __devexit ioh_gpio_remove(struct pci_dev *pdev)
int err;
int i;
struct ioh_gpio *chip = pci_get_drvdata(pdev);
- void __iomem *chip_save;
+ void *chip_save;
chip_save = chip;
diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c
index f0603297f829..68fa55e86eb1 100644
--- a/drivers/gpio/gpio-pch.c
+++ b/drivers/gpio/gpio-pch.c
@@ -231,7 +231,7 @@ static void pch_gpio_setup(struct pch_gpio *chip)
static int pch_irq_type(struct irq_data *d, unsigned int type)
{
u32 im;
- u32 *im_reg;
+ u32 __iomem *im_reg;
u32 ien;
u32 im_pos;
int ch;
@@ -376,7 +376,7 @@ static int __devinit pch_gpio_probe(struct pci_dev *pdev,
}
chip->base = pci_iomap(pdev, 1, 0);
- if (chip->base == 0) {
+ if (!chip->base) {
dev_err(&pdev->dev, "%s : pci_iomap FAILED", __func__);
ret = -ENOMEM;
goto err_iomap;
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c
index 8f79c03049f3..77c9cc70fa77 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 b6c1f6d80649..7eecf69362ee 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 4c980b573328..87a68a896abf 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 61044c889f7f..bdc293791590 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/gpio/gpio-tps65910.c b/drivers/gpio/gpio-tps65910.c
index b9c1c297669e..91f45b965d1e 100644
--- a/drivers/gpio/gpio-tps65910.c
+++ b/drivers/gpio/gpio-tps65910.c
@@ -52,7 +52,7 @@ static int tps65910_gpio_output(struct gpio_chip *gc, unsigned offset,
struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
/* Set the initial value */
- tps65910_gpio_set(gc, 0, value);
+ tps65910_gpio_set(gc, offset, value);
return tps65910_set_bits(tps65910, TPS65910_GPIO0 + offset,
GPIO_CFG_MASK);
diff --git a/drivers/gpu/drm/gma500/cdv_intel_crt.c b/drivers/gpu/drm/gma500/cdv_intel_crt.c
index 6d0f10b7569c..c100f3e9c920 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 50d7cfb51662..de25560e629d 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/gtt.c b/drivers/gpu/drm/gma500/gtt.c
index e770bd190a5c..5d5330f667f1 100644
--- a/drivers/gpu/drm/gma500/gtt.c
+++ b/drivers/gpu/drm/gma500/gtt.c
@@ -20,6 +20,7 @@
*/
#include <drm/drmP.h>
+#include <linux/shmem_fs.h>
#include "psb_drv.h"
@@ -203,9 +204,7 @@ static int psb_gtt_attach_pages(struct gtt_range *gt)
gt->npage = pages;
for (i = 0; i < pages; i++) {
- /* FIXME: needs updating as per mail from Hugh Dickins */
- p = read_cache_page_gfp(mapping, i,
- __GFP_COLD | GFP_KERNEL);
+ p = shmem_read_mapping_page(mapping, i);
if (IS_ERR(p))
goto err;
gt->pages[i] = p;
diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi.c b/drivers/gpu/drm/gma500/oaktrail_hdmi.c
index 36878a60080d..025d30970cc0 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 4882b29119e0..88b42971c0fd 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 525744d593c1..7814a760c164 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 38134a9c7578..b82709828931 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 f5e98910d17f..f80c5e0762ff 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 f7442e62c03f..8e8cd85e5c00 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 3ec81c3d5108..bfd36ab643a6 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 31da622eef63..8032f1fedb11 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 803e0d3c1773..ec46eb45e34c 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 37ead6995c87..0c46d8cdc6ea 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 f779009104eb..b71b77ab0dc7 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/hwmon/Kconfig b/drivers/hwmon/Kconfig
index cb351d358387..02260406b9e4 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 65a35cf5b3c5..3b728e8f169b 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 d30855a75786..34a14a77e008 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 522860ab6ce8..554f046bcf20 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 1ad0a885c5a5..0158cc35cb2e 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 e6291dafa4ca..97e2cfb0bc93 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 cfcc3b6fb6bf..ed60242d6a0a 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 1fdef885341c..a6c6ec36615e 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 d9803958e49f..ffb229af7861 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 848a2b0bc83f..865063914d76 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 38c0b87676de..0054d6f9cec9 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 508cb291f71b..5e6457a6644d 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 bdfd675488ae..d2dd5f90496d 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 3b43df418613..8bd6c5c9e05b 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 84ef3a898707..482ca901db30 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 6914195cfd35..88953f99e914 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 bde50e34d013..374118f2b9f9 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 65b685e2c7b7..17a8fa2d9ae9 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 6e5d0ae594b0..35aa5149307a 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 9ded133e43f0..d3100eab6b2f 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 3cc6fef22087..45ec7e7c3c27 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 3ee398d0e4c9..aa58b25565bc 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 0254e181893d..063bd9508d8a 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 a3afac4be734..3101dd59e379 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.
@@ -682,19 +682,19 @@ config I2C_XILINX
will be called xilinx_i2c.
config I2C_EG20T
- tristate "Intel EG20T PCH / OKI SEMICONDUCTOR IOH(ML7213/ML7223)"
+ tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) I2C"
depends on PCI
help
This driver is for PCH(Platform controller Hub) I2C of EG20T which
is an IOH(Input/Output Hub) for x86 embedded processor.
This driver can access PCH I2C bus device.
- 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.
comment "External I2C/SMBus adapter drivers"
diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c
index b6807db7b36f..e66d248fc126 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 a409cfcf0629..47ae0091e027 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 83e8a60cdc86..087ea9caa74d 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 03bcd07c4697..eb778bf15c18 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 6b6a6b1d7025..e5ac53b99b04 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 305c07504f7e..1679deef9c89 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 f314d7f433d3..582d616db346 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 b1d9cd28d8da..c1e1096ba069 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 9e89e7313d62..37f42113af31 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 18936ac9d51c..ca8877641040 100644
--- a/drivers/i2c/busses/i2c-eg20t.c
+++ b/drivers/i2c/busses/i2c-eg20t.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 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 as published by
@@ -136,7 +136,8 @@
/*
Set the number of I2C instance max
Intel EG20T PCH : 1ch
-OKI SEMICONDUCTOR ML7213 IOH : 2ch
+LAPIS Semiconductor ML7213 IOH : 2ch
+LAPIS Semiconductor ML7831 IOH : 1ch
*/
#define PCH_I2C_MAX_DEV 2
@@ -180,15 +181,17 @@ static int pch_clk = 50000; /* specifies I2C clock speed in KHz */
static wait_queue_head_t pch_event;
static DEFINE_MUTEX(pch_mutex);
-/* Definition for ML7213 by OKI SEMICONDUCTOR */
+/* Definition for ML7213 by LAPIS Semiconductor */
#define PCI_VENDOR_ID_ROHM 0x10DB
#define PCI_DEVICE_ID_ML7213_I2C 0x802D
#define PCI_DEVICE_ID_ML7223_I2C 0x8010
+#define PCI_DEVICE_ID_ML7831_I2C 0x8817
-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, },
+ { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7831_I2C), 1, },
{0,}
};
@@ -243,7 +246,7 @@ static void pch_i2c_init(struct i2c_algo_pch_data *adap)
if (pch_clk > PCH_MAX_CLK)
pch_clk = 62500;
- pch_i2cbc = (pch_clk + (pch_i2c_speed * 4)) / pch_i2c_speed * 8;
+ pch_i2cbc = (pch_clk + (pch_i2c_speed * 4)) / (pch_i2c_speed * 8);
/* Set transfer speed in I2CBC */
iowrite32(pch_i2cbc, p + PCH_I2CBC);
@@ -918,7 +921,9 @@ static int __devinit pch_i2c_probe(struct pci_dev *pdev,
pch_adap->dev.parent = &pdev->dev;
pch_i2c_init(&adap_info->pch_data[i]);
- ret = i2c_add_adapter(pch_adap);
+
+ pch_adap->nr = i;
+ ret = i2c_add_numbered_adapter(pch_adap);
if (ret) {
pch_pci_err(pdev, "i2c_add_adapter[ch:%d] FAILED\n", i);
goto err_add_adapter;
@@ -1058,8 +1063,8 @@ static void __exit pch_pci_exit(void)
}
module_exit(pch_pci_exit);
-MODULE_DESCRIPTION("Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH I2C Driver");
+MODULE_DESCRIPTION("Intel EG20T PCH/LAPIS Semico ML7213/ML7223/ML7831 IOH I2C");
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Tomoya MORINAGA. <tomoya-linux@dsn.okisemi.com>");
+MODULE_AUTHOR("Tomoya MORINAGA. <tomoya-linux@dsn.lapis-semi.com>");
module_param(pch_i2c_speed, int, (S_IRUSR | S_IWUSR));
module_param(pch_clk, int, (S_IRUSR | S_IWUSR));
diff --git a/drivers/i2c/busses/i2c-highlander.c b/drivers/i2c/busses/i2c-highlander.c
index 63bb1cc2a042..19515df61021 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 9ff1695d8458..c527de17db4f 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 ab26840d0c70..5d2e2816831f 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 3c110fbc409b..806e225f3de7 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 e828ac85cfa7..365bad5b890b 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 f09c9319a2ba..93f147a96b62 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 0682f8f277b0..6561d275b8cf 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 c01e9519f6c1..5d263f9014d6 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 107397a606b4..a8ebb84e23f9 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 a9941c65f226..4f44a33017b0 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 ff1e127dfea8..43a96a123920 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 1b46a9d9f907..18068dee48f1 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 56dbe54e8811..ee139a598814 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-omap.c b/drivers/i2c/busses/i2c-omap.c
index fa23faa20f0e..f713eac55047 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -37,6 +37,9 @@
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_i2c.h>
+#include <linux/of_device.h>
#include <linux/slab.h>
#include <linux/i2c-omap.h>
#include <linux/pm_runtime.h>
@@ -182,7 +185,9 @@ struct omap_i2c_dev {
u32 latency; /* maximum mpu wkup latency */
void (*set_mpu_wkup_lat)(struct device *dev,
long latency);
- u32 speed; /* Speed of bus in Khz */
+ u32 speed; /* Speed of bus in kHz */
+ u32 dtrev; /* extra revision from DT */
+ u32 flags;
u16 cmd_err;
u8 *buf;
u8 *regs;
@@ -235,7 +240,7 @@ static const u8 reg_map_ip_v2[] = {
[OMAP_I2C_BUF_REG] = 0x94,
[OMAP_I2C_CNT_REG] = 0x98,
[OMAP_I2C_DATA_REG] = 0x9c,
- [OMAP_I2C_SYSC_REG] = 0x20,
+ [OMAP_I2C_SYSC_REG] = 0x10,
[OMAP_I2C_CON_REG] = 0xa4,
[OMAP_I2C_OA_REG] = 0xa8,
[OMAP_I2C_SA_REG] = 0xac,
@@ -266,11 +271,7 @@ static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg)
static void omap_i2c_unidle(struct omap_i2c_dev *dev)
{
- struct omap_i2c_bus_platform_data *pdata;
-
- pdata = dev->dev->platform_data;
-
- if (pdata->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) {
+ if (dev->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) {
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, dev->pscstate);
omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, dev->scllstate);
@@ -291,13 +292,10 @@ static void omap_i2c_unidle(struct omap_i2c_dev *dev)
static void omap_i2c_idle(struct omap_i2c_dev *dev)
{
- struct omap_i2c_bus_platform_data *pdata;
u16 iv;
- pdata = dev->dev->platform_data;
-
dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
- if (pdata->rev == OMAP_I2C_IP_VERSION_2)
+ if (dev->dtrev == OMAP_I2C_IP_VERSION_2)
omap_i2c_write_reg(dev, OMAP_I2C_IP_V2_IRQENABLE_CLR, 1);
else
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0);
@@ -320,9 +318,6 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
unsigned long timeout;
unsigned long internal_clk = 0;
struct clk *fclk;
- struct omap_i2c_bus_platform_data *pdata;
-
- pdata = dev->dev->platform_data;
if (dev->rev >= OMAP_I2C_OMAP1_REV_2) {
/* Disable I2C controller before soft reset */
@@ -373,7 +368,7 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
}
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
- if (pdata->flags & OMAP_I2C_FLAG_ALWAYS_ARMXOR_CLK) {
+ if (dev->flags & OMAP_I2C_FLAG_ALWAYS_ARMXOR_CLK) {
/*
* The I2C functional clock is the armxor_ck, so there's
* no need to get "armxor_ck" separately. Now, if OMAP2420
@@ -397,7 +392,7 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
psc = fclk_rate / 12000000;
}
- if (!(pdata->flags & OMAP_I2C_FLAG_SIMPLE_CLOCK)) {
+ if (!(dev->flags & OMAP_I2C_FLAG_SIMPLE_CLOCK)) {
/*
* HSI2C controller internal clk rate should be 19.2 Mhz for
@@ -406,7 +401,7 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
* The filter is iclk (fclk for HS) period.
*/
if (dev->speed > 400 ||
- pdata->flags & OMAP_I2C_FLAG_FORCE_19200_INT_CLK)
+ dev->flags & OMAP_I2C_FLAG_FORCE_19200_INT_CLK)
internal_clk = 19200;
else if (dev->speed > 100)
internal_clk = 9600;
@@ -475,7 +470,7 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
dev->errata = 0;
- if (pdata->flags & OMAP_I2C_FLAG_APPLY_ERRATA_I207)
+ if (dev->flags & OMAP_I2C_FLAG_APPLY_ERRATA_I207)
dev->errata |= I2C_OMAP_ERRATA_I207;
/* Enable interrupts */
@@ -484,7 +479,7 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
OMAP_I2C_IE_AL) | ((dev->fifo_size) ?
(OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0);
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
- if (pdata->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) {
+ if (dev->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) {
dev->pscstate = psc;
dev->scllstate = scll;
dev->sclhstate = sclh;
@@ -804,9 +799,6 @@ omap_i2c_isr(int this_irq, void *dev_id)
u16 bits;
u16 stat, w;
int err, count = 0;
- struct omap_i2c_bus_platform_data *pdata;
-
- pdata = dev->dev->platform_data;
if (pm_runtime_suspended(dev->dev))
return IRQ_NONE;
@@ -830,11 +822,9 @@ complete:
~(OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR |
OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
- if (stat & OMAP_I2C_STAT_NACK) {
+ if (stat & OMAP_I2C_STAT_NACK)
err |= OMAP_I2C_STAT_NACK;
- omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
- OMAP_I2C_CON_STP);
- }
+
if (stat & OMAP_I2C_STAT_AL) {
dev_err(dev->dev, "Arbitration lost\n");
err |= OMAP_I2C_STAT_AL;
@@ -875,7 +865,7 @@ complete:
* Data reg in 2430, omap3 and
* omap4 is 8 bit wide
*/
- if (pdata->flags &
+ if (dev->flags &
OMAP_I2C_FLAG_16BIT_DATA_REG) {
if (dev->buf_len) {
*dev->buf++ = w >> 8;
@@ -918,7 +908,7 @@ complete:
* Data reg in 2430, omap3 and
* omap4 is 8 bit wide
*/
- if (pdata->flags &
+ if (dev->flags &
OMAP_I2C_FLAG_16BIT_DATA_REG) {
if (dev->buf_len) {
w |= *dev->buf++ << 8;
@@ -965,6 +955,32 @@ static const struct i2c_algorithm omap_i2c_algo = {
.functionality = omap_i2c_func,
};
+#ifdef CONFIG_OF
+static struct omap_i2c_bus_platform_data omap3_pdata = {
+ .rev = OMAP_I2C_IP_VERSION_1,
+ .flags = OMAP_I2C_FLAG_APPLY_ERRATA_I207 |
+ OMAP_I2C_FLAG_RESET_REGS_POSTIDLE |
+ OMAP_I2C_FLAG_BUS_SHIFT_2,
+};
+
+static struct omap_i2c_bus_platform_data omap4_pdata = {
+ .rev = OMAP_I2C_IP_VERSION_2,
+};
+
+static const struct of_device_id omap_i2c_of_match[] = {
+ {
+ .compatible = "ti,omap4-i2c",
+ .data = &omap4_pdata,
+ },
+ {
+ .compatible = "ti,omap3-i2c",
+ .data = &omap3_pdata,
+ },
+ { },
+};
+MODULE_DEVICE_TABLE(of, omap_i2c_of_match);
+#endif
+
static int __devinit
omap_i2c_probe(struct platform_device *pdev)
{
@@ -972,9 +988,10 @@ omap_i2c_probe(struct platform_device *pdev)
struct i2c_adapter *adap;
struct resource *mem, *irq, *ioarea;
struct omap_i2c_bus_platform_data *pdata = pdev->dev.platform_data;
+ struct device_node *node = pdev->dev.of_node;
+ const struct of_device_id *match;
irq_handler_t isr;
int r;
- u32 speed = 0;
/* NOTE: driver uses the static register mapping */
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1001,15 +1018,24 @@ omap_i2c_probe(struct platform_device *pdev)
goto err_release_region;
}
- if (pdata != NULL) {
- speed = pdata->clkrate;
+ match = of_match_device(omap_i2c_of_match, &pdev->dev);
+ if (match) {
+ u32 freq = 100000; /* default to 100000 Hz */
+
+ pdata = match->data;
+ dev->dtrev = pdata->rev;
+ dev->flags = pdata->flags;
+
+ of_property_read_u32(node, "clock-frequency", &freq);
+ /* convert DT freq value in Hz into kHz for speed */
+ dev->speed = freq / 1000;
+ } else if (pdata != NULL) {
+ dev->speed = pdata->clkrate;
+ dev->flags = pdata->flags;
dev->set_mpu_wkup_lat = pdata->set_mpu_wkup_lat;
- } else {
- speed = 100; /* Default speed */
- dev->set_mpu_wkup_lat = NULL;
+ dev->dtrev = pdata->rev;
}
- dev->speed = speed;
dev->dev = &pdev->dev;
dev->irq = irq->start;
dev->base = ioremap(mem->start, resource_size(mem));
@@ -1020,9 +1046,9 @@ omap_i2c_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, dev);
- dev->reg_shift = (pdata->flags >> OMAP_I2C_FLAG_BUS_SHIFT__SHIFT) & 3;
+ dev->reg_shift = (dev->flags >> OMAP_I2C_FLAG_BUS_SHIFT__SHIFT) & 3;
- if (pdata->rev == OMAP_I2C_IP_VERSION_2)
+ if (dev->dtrev == OMAP_I2C_IP_VERSION_2)
dev->regs = (u8 *)reg_map_ip_v2;
else
dev->regs = (u8 *)reg_map_ip_v1;
@@ -1035,7 +1061,7 @@ omap_i2c_probe(struct platform_device *pdev)
if (dev->rev <= OMAP_I2C_REV_ON_3430)
dev->errata |= I2C_OMAP3_1P153;
- if (!(pdata->flags & OMAP_I2C_FLAG_NO_FIFO)) {
+ if (!(dev->flags & OMAP_I2C_FLAG_NO_FIFO)) {
u16 s;
/* Set up the fifo size - Get total size */
@@ -1058,7 +1084,7 @@ omap_i2c_probe(struct platform_device *pdev)
/* calculate wakeup latency constraint for MPU */
if (dev->set_mpu_wkup_lat != NULL)
dev->latency = (1000000 * dev->fifo_size) /
- (1000 * speed / 8);
+ (1000 * dev->speed / 8);
}
/* reset ASAP, clearing any IRQs */
@@ -1074,7 +1100,7 @@ omap_i2c_probe(struct platform_device *pdev)
}
dev_info(dev->dev, "bus %d rev%d.%d.%d at %d kHz\n", pdev->id,
- pdata->rev, dev->rev >> 4, dev->rev & 0xf, dev->speed);
+ dev->dtrev, dev->rev >> 4, dev->rev & 0xf, dev->speed);
pm_runtime_put(dev->dev);
@@ -1085,6 +1111,7 @@ omap_i2c_probe(struct platform_device *pdev)
strlcpy(adap->name, "OMAP I2C adapter", sizeof(adap->name));
adap->algo = &omap_i2c_algo;
adap->dev.parent = &pdev->dev;
+ adap->dev.of_node = pdev->dev.of_node;
/* i2c device drivers may be active on return from add_adapter() */
adap->nr = pdev->id;
@@ -1094,6 +1121,8 @@ omap_i2c_probe(struct platform_device *pdev)
goto err_free_irq;
}
+ of_i2c_register_devices(adap);
+
return 0;
err_free_irq:
@@ -1166,6 +1195,7 @@ static struct platform_driver omap_i2c_driver = {
.name = "omap_i2c",
.owner = THIS_MODULE,
.pm = OMAP_I2C_PM_OPS,
+ .of_match_table = of_match_ptr(omap_i2c_of_match),
},
};
diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c
index 837b8c1aa02a..eaaea73209c5 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 ace67995d7de..2adbf1a8fdea 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 6d14ac2e3c41..c14d48dd601a 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 127051b06921..07b7447ecbc9 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 b289ec99eeba..7b397c6f607e 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-pxa-pci.c b/drivers/i2c/busses/i2c-pxa-pci.c
index 632e088760a3..a05817980556 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 a67132b2e092..c0c9dffbdb12 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 2fc08fbf67a2..4fc87e7c94c9 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 437586611d4a..87e5126d449c 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 e6f539e26f65..15cf78f65ce0 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 86837f0c4cb9..cc5d149413f7 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 7799fe5bda88..713d31ade26b 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 0b012f1f8ac5..333011c83d52 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 ac083a28ae08..2bded7647ef2 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 91e349c884c5..2eacb7784d56 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 57a45ce84b2d..10e7f1e76586 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 7b6ce624cd6e..e5fa695eb0fa 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 25b9fe3a9f8e..d3be99fb4154 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 a81bd7575792..14717304b388 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 6929f7fce93a..46af4743b3e6 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 3feaa26410be..51beb85250d4 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 808bcdcbf8e1..986f2513eab4 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 979d342c338a..547d7cf2e016 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 f22edc66b030..f1a6796b165c 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 d267b7affad6..a22ca8467010 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 a743e68a8903..7f56b738d762 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 3f0244fd8e62..8bbfe5557c7b 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 47adcd09cb26..5cfb78120669 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/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 5d2f8e13cf0e..20bce51c2e82 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -197,7 +197,7 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
.enter = &intel_idle },
};
-static int get_driver_data(int cstate)
+static long get_driver_data(int cstate)
{
int driver_data;
switch (cstate) {
@@ -232,6 +232,7 @@ static int get_driver_data(int cstate)
* @drv: cpuidle driver
* @index: index of cpuidle state
*
+ * Must be called under local_irq_disable().
*/
static int intel_idle(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index)
@@ -247,8 +248,6 @@ static int intel_idle(struct cpuidle_device *dev,
cstate = (((eax) >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK) + 1;
- local_irq_disable();
-
/*
* leave_mm() to avoid costly and often unnecessary wakeups
* for flushing the user TLB's associated with the active mm.
@@ -348,7 +347,8 @@ static int intel_idle_probe(void)
cpuid(CPUID_MWAIT_LEAF, &eax, &ebx, &ecx, &mwait_substates);
if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED) ||
- !(ecx & CPUID5_ECX_INTERRUPT_BREAK))
+ !(ecx & CPUID5_ECX_INTERRUPT_BREAK) ||
+ !mwait_substates)
return -ENODEV;
pr_debug(PREFIX "MWAIT substates: 0x%x\n", mwait_substates);
@@ -394,7 +394,7 @@ static int intel_idle_probe(void)
if (boot_cpu_has(X86_FEATURE_ARAT)) /* Always Reliable APIC Timer */
lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE;
else {
- smp_call_function(__setup_broadcast_timer, (void *)true, 1);
+ on_each_cpu(__setup_broadcast_timer, (void *)true, 1);
register_cpu_notifier(&setup_broadcast_notifier);
}
@@ -471,71 +471,67 @@ static int intel_idle_cpuidle_driver_init(void)
}
if (auto_demotion_disable_flags)
- smp_call_function(auto_demotion_disable, NULL, 1);
+ on_each_cpu(auto_demotion_disable, NULL, 1);
return 0;
}
/*
- * intel_idle_cpuidle_devices_init()
+ * intel_idle_cpu_init()
* allocate, initialize, register cpuidle_devices
+ * @cpu: cpu/core to initialize
*/
-static int intel_idle_cpuidle_devices_init(void)
+int intel_idle_cpu_init(int cpu)
{
- int i, cstate;
+ int cstate;
struct cpuidle_device *dev;
- intel_idle_cpuidle_devices = alloc_percpu(struct cpuidle_device);
- if (intel_idle_cpuidle_devices == NULL)
- return -ENOMEM;
-
- for_each_online_cpu(i) {
- dev = per_cpu_ptr(intel_idle_cpuidle_devices, i);
+ dev = per_cpu_ptr(intel_idle_cpuidle_devices, cpu);
- dev->state_count = 1;
+ dev->state_count = 1;
- for (cstate = 1; cstate < MWAIT_MAX_NUM_CSTATES; ++cstate) {
- int num_substates;
+ for (cstate = 1; cstate < MWAIT_MAX_NUM_CSTATES; ++cstate) {
+ int num_substates;
- if (cstate > max_cstate) {
- printk(PREFIX "max_cstate %d reached\n",
- max_cstate);
- break;
- }
+ if (cstate > max_cstate) {
+ printk(PREFIX "max_cstate %d reached\n",
+ max_cstate);
+ break;
+ }
- /* does the state exist in CPUID.MWAIT? */
- num_substates = (mwait_substates >> ((cstate) * 4))
- & MWAIT_SUBSTATE_MASK;
- if (num_substates == 0)
- continue;
- /* is the state not enabled? */
- if (cpuidle_state_table[cstate].enter == NULL) {
- continue;
- }
+ /* does the state exist in CPUID.MWAIT? */
+ num_substates = (mwait_substates >> ((cstate) * 4))
+ & MWAIT_SUBSTATE_MASK;
+ if (num_substates == 0)
+ continue;
+ /* is the state not enabled? */
+ if (cpuidle_state_table[cstate].enter == NULL)
+ continue;
- dev->states_usage[dev->state_count].driver_data =
- (void *)get_driver_data(cstate);
+ dev->states_usage[dev->state_count].driver_data =
+ (void *)get_driver_data(cstate);
dev->state_count += 1;
}
+ dev->cpu = cpu;
- dev->cpu = i;
- if (cpuidle_register_device(dev)) {
- pr_debug(PREFIX "cpuidle_register_device %d failed!\n",
- i);
- intel_idle_cpuidle_devices_uninit();
- return -EIO;
- }
+ if (cpuidle_register_device(dev)) {
+ pr_debug(PREFIX "cpuidle_register_device %d failed!\n", cpu);
+ intel_idle_cpuidle_devices_uninit();
+ return -EIO;
}
+ if (auto_demotion_disable_flags)
+ smp_call_function_single(cpu, auto_demotion_disable, NULL, 1);
+
return 0;
}
static int __init intel_idle_init(void)
{
- int retval;
+ int retval, i;
/* Do not load intel_idle at all for now if idle= is passed */
if (boot_option_idle_override != IDLE_NO_OVERRIDE)
@@ -553,10 +549,16 @@ static int __init intel_idle_init(void)
return retval;
}
- retval = intel_idle_cpuidle_devices_init();
- if (retval) {
- cpuidle_unregister_driver(&intel_idle_driver);
- return retval;
+ intel_idle_cpuidle_devices = alloc_percpu(struct cpuidle_device);
+ if (intel_idle_cpuidle_devices == NULL)
+ return -ENOMEM;
+
+ for_each_online_cpu(i) {
+ retval = intel_idle_cpu_init(i);
+ if (retval) {
+ cpuidle_unregister_driver(&intel_idle_driver);
+ return retval;
+ }
}
return 0;
@@ -568,7 +570,7 @@ static void __exit intel_idle_exit(void)
cpuidle_unregister_driver(&intel_idle_driver);
if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE) {
- smp_call_function(__setup_broadcast_timer, (void *)false, 1);
+ on_each_cpu(__setup_broadcast_timer, (void *)false, 1);
unregister_cpu_notifier(&setup_broadcast_notifier);
}
diff --git a/drivers/infiniband/Kconfig b/drivers/infiniband/Kconfig
index 0f9a84c1046a..eb0add311dc8 100644
--- a/drivers/infiniband/Kconfig
+++ b/drivers/infiniband/Kconfig
@@ -55,6 +55,7 @@ source "drivers/infiniband/hw/nes/Kconfig"
source "drivers/infiniband/ulp/ipoib/Kconfig"
source "drivers/infiniband/ulp/srp/Kconfig"
+source "drivers/infiniband/ulp/srpt/Kconfig"
source "drivers/infiniband/ulp/iser/Kconfig"
diff --git a/drivers/infiniband/Makefile b/drivers/infiniband/Makefile
index 9cc7a47d3e67..a3b2d8eac86e 100644
--- a/drivers/infiniband/Makefile
+++ b/drivers/infiniband/Makefile
@@ -10,4 +10,5 @@ obj-$(CONFIG_MLX4_INFINIBAND) += hw/mlx4/
obj-$(CONFIG_INFINIBAND_NES) += hw/nes/
obj-$(CONFIG_INFINIBAND_IPOIB) += ulp/ipoib/
obj-$(CONFIG_INFINIBAND_SRP) += ulp/srp/
+obj-$(CONFIG_INFINIBAND_SRPT) += ulp/srpt/
obj-$(CONFIG_INFINIBAND_ISER) += ulp/iser/
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
index aaf6023a4835..f08f6eaf3fa8 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 c240e9972cb0..832e7a7d0aee 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 5965b3df8f2f..7013da5e9eda 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/infiniband/ulp/srpt/Kconfig b/drivers/infiniband/ulp/srpt/Kconfig
new file mode 100644
index 000000000000..31ee83d528d9
--- /dev/null
+++ b/drivers/infiniband/ulp/srpt/Kconfig
@@ -0,0 +1,12 @@
+config INFINIBAND_SRPT
+ tristate "InfiniBand SCSI RDMA Protocol target support"
+ depends on INFINIBAND && TARGET_CORE
+ ---help---
+
+ Support for the SCSI RDMA Protocol (SRP) Target driver. The
+ SRP protocol is a protocol that allows an initiator to access
+ a block storage device on another host (target) over a network
+ that supports the RDMA protocol. Currently the RDMA protocol is
+ supported by InfiniBand and by iWarp network hardware. More
+ information about the SRP protocol can be found on the website
+ of the INCITS T10 technical committee (http://www.t10.org/).
diff --git a/drivers/infiniband/ulp/srpt/Makefile b/drivers/infiniband/ulp/srpt/Makefile
new file mode 100644
index 000000000000..e3ee4bdfffa5
--- /dev/null
+++ b/drivers/infiniband/ulp/srpt/Makefile
@@ -0,0 +1,2 @@
+ccflags-y := -Idrivers/target
+obj-$(CONFIG_INFINIBAND_SRPT) += ib_srpt.o
diff --git a/drivers/infiniband/ulp/srpt/ib_dm_mad.h b/drivers/infiniband/ulp/srpt/ib_dm_mad.h
new file mode 100644
index 000000000000..fb1de1f6f297
--- /dev/null
+++ b/drivers/infiniband/ulp/srpt/ib_dm_mad.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2006 - 2009 Mellanox Technology Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef IB_DM_MAD_H
+#define IB_DM_MAD_H
+
+#include <linux/types.h>
+
+#include <rdma/ib_mad.h>
+
+enum {
+ /*
+ * See also section 13.4.7 Status Field, table 115 MAD Common Status
+ * Field Bit Values and also section 16.3.1.1 Status Field in the
+ * InfiniBand Architecture Specification.
+ */
+ DM_MAD_STATUS_UNSUP_METHOD = 0x0008,
+ DM_MAD_STATUS_UNSUP_METHOD_ATTR = 0x000c,
+ DM_MAD_STATUS_INVALID_FIELD = 0x001c,
+ DM_MAD_STATUS_NO_IOC = 0x0100,
+
+ /*
+ * See also the Device Management chapter, section 16.3.3 Attributes,
+ * table 279 Device Management Attributes in the InfiniBand
+ * Architecture Specification.
+ */
+ DM_ATTR_CLASS_PORT_INFO = 0x01,
+ DM_ATTR_IOU_INFO = 0x10,
+ DM_ATTR_IOC_PROFILE = 0x11,
+ DM_ATTR_SVC_ENTRIES = 0x12
+};
+
+struct ib_dm_hdr {
+ u8 reserved[28];
+};
+
+/*
+ * Structure of management datagram sent by the SRP target implementation.
+ * Contains a management datagram header, reliable multi-packet transaction
+ * protocol (RMPP) header and ib_dm_hdr. Notes:
+ * - The SRP target implementation does not use RMPP or ib_dm_hdr when sending
+ * management datagrams.
+ * - The header size must be exactly 64 bytes (IB_MGMT_DEVICE_HDR), since this
+ * is the header size that is passed to ib_create_send_mad() in ib_srpt.c.
+ * - The maximum supported size for a management datagram when not using RMPP
+ * is 256 bytes -- 64 bytes header and 192 (IB_MGMT_DEVICE_DATA) bytes data.
+ */
+struct ib_dm_mad {
+ struct ib_mad_hdr mad_hdr;
+ struct ib_rmpp_hdr rmpp_hdr;
+ struct ib_dm_hdr dm_hdr;
+ u8 data[IB_MGMT_DEVICE_DATA];
+};
+
+/*
+ * IOUnitInfo as defined in section 16.3.3.3 IOUnitInfo of the InfiniBand
+ * Architecture Specification.
+ */
+struct ib_dm_iou_info {
+ __be16 change_id;
+ u8 max_controllers;
+ u8 op_rom;
+ u8 controller_list[128];
+};
+
+/*
+ * IOControllerprofile as defined in section 16.3.3.4 IOControllerProfile of
+ * the InfiniBand Architecture Specification.
+ */
+struct ib_dm_ioc_profile {
+ __be64 guid;
+ __be32 vendor_id;
+ __be32 device_id;
+ __be16 device_version;
+ __be16 reserved1;
+ __be32 subsys_vendor_id;
+ __be32 subsys_device_id;
+ __be16 io_class;
+ __be16 io_subclass;
+ __be16 protocol;
+ __be16 protocol_version;
+ __be16 service_conn;
+ __be16 initiators_supported;
+ __be16 send_queue_depth;
+ u8 reserved2;
+ u8 rdma_read_depth;
+ __be32 send_size;
+ __be32 rdma_size;
+ u8 op_cap_mask;
+ u8 svc_cap_mask;
+ u8 num_svc_entries;
+ u8 reserved3[9];
+ u8 id_string[64];
+};
+
+struct ib_dm_svc_entry {
+ u8 name[40];
+ __be64 id;
+};
+
+/*
+ * See also section 16.3.3.5 ServiceEntries in the InfiniBand Architecture
+ * Specification. See also section B.7, table B.8 in the T10 SRP r16a document.
+ */
+struct ib_dm_svc_entries {
+ struct ib_dm_svc_entry service_entries[4];
+};
+
+#endif
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c
new file mode 100644
index 000000000000..cd5d05e22a77
--- /dev/null
+++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
@@ -0,0 +1,4073 @@
+/*
+ * Copyright (c) 2006 - 2009 Mellanox Technology Inc. All rights reserved.
+ * Copyright (C) 2008 - 2011 Bart Van Assche <bvanassche@acm.org>.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/ctype.h>
+#include <linux/kthread.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/atomic.h>
+#include <scsi/scsi_tcq.h>
+#include <target/configfs_macros.h>
+#include <target/target_core_base.h>
+#include <target/target_core_fabric_configfs.h>
+#include <target/target_core_fabric.h>
+#include <target/target_core_configfs.h>
+#include "ib_srpt.h"
+
+/* Name of this kernel module. */
+#define DRV_NAME "ib_srpt"
+#define DRV_VERSION "2.0.0"
+#define DRV_RELDATE "2011-02-14"
+
+#define SRPT_ID_STRING "Linux SRP target"
+
+#undef pr_fmt
+#define pr_fmt(fmt) DRV_NAME " " fmt
+
+MODULE_AUTHOR("Vu Pham and Bart Van Assche");
+MODULE_DESCRIPTION("InfiniBand SCSI RDMA Protocol target "
+ "v" DRV_VERSION " (" DRV_RELDATE ")");
+MODULE_LICENSE("Dual BSD/GPL");
+
+/*
+ * Global Variables
+ */
+
+static u64 srpt_service_guid;
+static spinlock_t srpt_dev_lock; /* Protects srpt_dev_list. */
+static struct list_head srpt_dev_list; /* List of srpt_device structures. */
+
+static unsigned srp_max_req_size = DEFAULT_MAX_REQ_SIZE;
+module_param(srp_max_req_size, int, 0444);
+MODULE_PARM_DESC(srp_max_req_size,
+ "Maximum size of SRP request messages in bytes.");
+
+static int srpt_srq_size = DEFAULT_SRPT_SRQ_SIZE;
+module_param(srpt_srq_size, int, 0444);
+MODULE_PARM_DESC(srpt_srq_size,
+ "Shared receive queue (SRQ) size.");
+
+static int srpt_get_u64_x(char *buffer, struct kernel_param *kp)
+{
+ return sprintf(buffer, "0x%016llx", *(u64 *)kp->arg);
+}
+module_param_call(srpt_service_guid, NULL, srpt_get_u64_x, &srpt_service_guid,
+ 0444);
+MODULE_PARM_DESC(srpt_service_guid,
+ "Using this value for ioc_guid, id_ext, and cm_listen_id"
+ " instead of using the node_guid of the first HCA.");
+
+static struct ib_client srpt_client;
+static struct target_fabric_configfs *srpt_target;
+static void srpt_release_channel(struct srpt_rdma_ch *ch);
+static int srpt_queue_status(struct se_cmd *cmd);
+
+/**
+ * opposite_dma_dir() - Swap DMA_TO_DEVICE and DMA_FROM_DEVICE.
+ */
+static inline
+enum dma_data_direction opposite_dma_dir(enum dma_data_direction dir)
+{
+ switch (dir) {
+ case DMA_TO_DEVICE: return DMA_FROM_DEVICE;
+ case DMA_FROM_DEVICE: return DMA_TO_DEVICE;
+ default: return dir;
+ }
+}
+
+/**
+ * srpt_sdev_name() - Return the name associated with the HCA.
+ *
+ * Examples are ib0, ib1, ...
+ */
+static inline const char *srpt_sdev_name(struct srpt_device *sdev)
+{
+ return sdev->device->name;
+}
+
+static enum rdma_ch_state srpt_get_ch_state(struct srpt_rdma_ch *ch)
+{
+ unsigned long flags;
+ enum rdma_ch_state state;
+
+ spin_lock_irqsave(&ch->spinlock, flags);
+ state = ch->state;
+ spin_unlock_irqrestore(&ch->spinlock, flags);
+ return state;
+}
+
+static enum rdma_ch_state
+srpt_set_ch_state(struct srpt_rdma_ch *ch, enum rdma_ch_state new_state)
+{
+ unsigned long flags;
+ enum rdma_ch_state prev;
+
+ spin_lock_irqsave(&ch->spinlock, flags);
+ prev = ch->state;
+ ch->state = new_state;
+ spin_unlock_irqrestore(&ch->spinlock, flags);
+ return prev;
+}
+
+/**
+ * srpt_test_and_set_ch_state() - Test and set the channel state.
+ *
+ * Returns true if and only if the channel state has been set to the new state.
+ */
+static bool
+srpt_test_and_set_ch_state(struct srpt_rdma_ch *ch, enum rdma_ch_state old,
+ enum rdma_ch_state new)
+{
+ unsigned long flags;
+ enum rdma_ch_state prev;
+
+ spin_lock_irqsave(&ch->spinlock, flags);
+ prev = ch->state;
+ if (prev == old)
+ ch->state = new;
+ spin_unlock_irqrestore(&ch->spinlock, flags);
+ return prev == old;
+}
+
+/**
+ * srpt_event_handler() - Asynchronous IB event callback function.
+ *
+ * Callback function called by the InfiniBand core when an asynchronous IB
+ * event occurs. This callback may occur in interrupt context. See also
+ * section 11.5.2, Set Asynchronous Event Handler in the InfiniBand
+ * Architecture Specification.
+ */
+static void srpt_event_handler(struct ib_event_handler *handler,
+ struct ib_event *event)
+{
+ struct srpt_device *sdev;
+ struct srpt_port *sport;
+
+ sdev = ib_get_client_data(event->device, &srpt_client);
+ if (!sdev || sdev->device != event->device)
+ return;
+
+ pr_debug("ASYNC event= %d on device= %s\n", event->event,
+ srpt_sdev_name(sdev));
+
+ switch (event->event) {
+ case IB_EVENT_PORT_ERR:
+ if (event->element.port_num <= sdev->device->phys_port_cnt) {
+ sport = &sdev->port[event->element.port_num - 1];
+ sport->lid = 0;
+ sport->sm_lid = 0;
+ }
+ break;
+ case IB_EVENT_PORT_ACTIVE:
+ case IB_EVENT_LID_CHANGE:
+ case IB_EVENT_PKEY_CHANGE:
+ case IB_EVENT_SM_CHANGE:
+ case IB_EVENT_CLIENT_REREGISTER:
+ /* Refresh port data asynchronously. */
+ if (event->element.port_num <= sdev->device->phys_port_cnt) {
+ sport = &sdev->port[event->element.port_num - 1];
+ if (!sport->lid && !sport->sm_lid)
+ schedule_work(&sport->work);
+ }
+ break;
+ default:
+ printk(KERN_ERR "received unrecognized IB event %d\n",
+ event->event);
+ break;
+ }
+}
+
+/**
+ * srpt_srq_event() - SRQ event callback function.
+ */
+static void srpt_srq_event(struct ib_event *event, void *ctx)
+{
+ printk(KERN_INFO "SRQ event %d\n", event->event);
+}
+
+/**
+ * srpt_qp_event() - QP event callback function.
+ */
+static void srpt_qp_event(struct ib_event *event, struct srpt_rdma_ch *ch)
+{
+ pr_debug("QP event %d on cm_id=%p sess_name=%s state=%d\n",
+ event->event, ch->cm_id, ch->sess_name, srpt_get_ch_state(ch));
+
+ switch (event->event) {
+ case IB_EVENT_COMM_EST:
+ ib_cm_notify(ch->cm_id, event->event);
+ break;
+ case IB_EVENT_QP_LAST_WQE_REACHED:
+ if (srpt_test_and_set_ch_state(ch, CH_DRAINING,
+ CH_RELEASING))
+ srpt_release_channel(ch);
+ else
+ pr_debug("%s: state %d - ignored LAST_WQE.\n",
+ ch->sess_name, srpt_get_ch_state(ch));
+ break;
+ default:
+ printk(KERN_ERR "received unrecognized IB QP event %d\n",
+ event->event);
+ break;
+ }
+}
+
+/**
+ * srpt_set_ioc() - Helper function for initializing an IOUnitInfo structure.
+ *
+ * @slot: one-based slot number.
+ * @value: four-bit value.
+ *
+ * Copies the lowest four bits of value in element slot of the array of four
+ * bit elements called c_list (controller list). The index slot is one-based.
+ */
+static void srpt_set_ioc(u8 *c_list, u32 slot, u8 value)
+{
+ u16 id;
+ u8 tmp;
+
+ id = (slot - 1) / 2;
+ if (slot & 0x1) {
+ tmp = c_list[id] & 0xf;
+ c_list[id] = (value << 4) | tmp;
+ } else {
+ tmp = c_list[id] & 0xf0;
+ c_list[id] = (value & 0xf) | tmp;
+ }
+}
+
+/**
+ * srpt_get_class_port_info() - Copy ClassPortInfo to a management datagram.
+ *
+ * See also section 16.3.3.1 ClassPortInfo in the InfiniBand Architecture
+ * Specification.
+ */
+static void srpt_get_class_port_info(struct ib_dm_mad *mad)
+{
+ struct ib_class_port_info *cif;
+
+ cif = (struct ib_class_port_info *)mad->data;
+ memset(cif, 0, sizeof *cif);
+ cif->base_version = 1;
+ cif->class_version = 1;
+ cif->resp_time_value = 20;
+
+ mad->mad_hdr.status = 0;
+}
+
+/**
+ * srpt_get_iou() - Write IOUnitInfo to a management datagram.
+ *
+ * See also section 16.3.3.3 IOUnitInfo in the InfiniBand Architecture
+ * Specification. See also section B.7, table B.6 in the SRP r16a document.
+ */
+static void srpt_get_iou(struct ib_dm_mad *mad)
+{
+ struct ib_dm_iou_info *ioui;
+ u8 slot;
+ int i;
+
+ ioui = (struct ib_dm_iou_info *)mad->data;
+ ioui->change_id = __constant_cpu_to_be16(1);
+ ioui->max_controllers = 16;
+
+ /* set present for slot 1 and empty for the rest */
+ srpt_set_ioc(ioui->controller_list, 1, 1);
+ for (i = 1, slot = 2; i < 16; i++, slot++)
+ srpt_set_ioc(ioui->controller_list, slot, 0);
+
+ mad->mad_hdr.status = 0;
+}
+
+/**
+ * srpt_get_ioc() - Write IOControllerprofile to a management datagram.
+ *
+ * See also section 16.3.3.4 IOControllerProfile in the InfiniBand
+ * Architecture Specification. See also section B.7, table B.7 in the SRP
+ * r16a document.
+ */
+static void srpt_get_ioc(struct srpt_port *sport, u32 slot,
+ struct ib_dm_mad *mad)
+{
+ struct srpt_device *sdev = sport->sdev;
+ struct ib_dm_ioc_profile *iocp;
+
+ iocp = (struct ib_dm_ioc_profile *)mad->data;
+
+ if (!slot || slot > 16) {
+ mad->mad_hdr.status
+ = __constant_cpu_to_be16(DM_MAD_STATUS_INVALID_FIELD);
+ return;
+ }
+
+ if (slot > 2) {
+ mad->mad_hdr.status
+ = __constant_cpu_to_be16(DM_MAD_STATUS_NO_IOC);
+ return;
+ }
+
+ memset(iocp, 0, sizeof *iocp);
+ strcpy(iocp->id_string, SRPT_ID_STRING);
+ iocp->guid = cpu_to_be64(srpt_service_guid);
+ iocp->vendor_id = cpu_to_be32(sdev->dev_attr.vendor_id);
+ iocp->device_id = cpu_to_be32(sdev->dev_attr.vendor_part_id);
+ iocp->device_version = cpu_to_be16(sdev->dev_attr.hw_ver);
+ iocp->subsys_vendor_id = cpu_to_be32(sdev->dev_attr.vendor_id);
+ iocp->subsys_device_id = 0x0;
+ iocp->io_class = __constant_cpu_to_be16(SRP_REV16A_IB_IO_CLASS);
+ iocp->io_subclass = __constant_cpu_to_be16(SRP_IO_SUBCLASS);
+ iocp->protocol = __constant_cpu_to_be16(SRP_PROTOCOL);
+ iocp->protocol_version = __constant_cpu_to_be16(SRP_PROTOCOL_VERSION);
+ iocp->send_queue_depth = cpu_to_be16(sdev->srq_size);
+ iocp->rdma_read_depth = 4;
+ iocp->send_size = cpu_to_be32(srp_max_req_size);
+ iocp->rdma_size = cpu_to_be32(min(sport->port_attrib.srp_max_rdma_size,
+ 1U << 24));
+ iocp->num_svc_entries = 1;
+ iocp->op_cap_mask = SRP_SEND_TO_IOC | SRP_SEND_FROM_IOC |
+ SRP_RDMA_READ_FROM_IOC | SRP_RDMA_WRITE_FROM_IOC;
+
+ mad->mad_hdr.status = 0;
+}
+
+/**
+ * srpt_get_svc_entries() - Write ServiceEntries to a management datagram.
+ *
+ * See also section 16.3.3.5 ServiceEntries in the InfiniBand Architecture
+ * Specification. See also section B.7, table B.8 in the SRP r16a document.
+ */
+static void srpt_get_svc_entries(u64 ioc_guid,
+ u16 slot, u8 hi, u8 lo, struct ib_dm_mad *mad)
+{
+ struct ib_dm_svc_entries *svc_entries;
+
+ WARN_ON(!ioc_guid);
+
+ if (!slot || slot > 16) {
+ mad->mad_hdr.status
+ = __constant_cpu_to_be16(DM_MAD_STATUS_INVALID_FIELD);
+ return;
+ }
+
+ if (slot > 2 || lo > hi || hi > 1) {
+ mad->mad_hdr.status
+ = __constant_cpu_to_be16(DM_MAD_STATUS_NO_IOC);
+ return;
+ }
+
+ svc_entries = (struct ib_dm_svc_entries *)mad->data;
+ memset(svc_entries, 0, sizeof *svc_entries);
+ svc_entries->service_entries[0].id = cpu_to_be64(ioc_guid);
+ snprintf(svc_entries->service_entries[0].name,
+ sizeof(svc_entries->service_entries[0].name),
+ "%s%016llx",
+ SRP_SERVICE_NAME_PREFIX,
+ ioc_guid);
+
+ mad->mad_hdr.status = 0;
+}
+
+/**
+ * srpt_mgmt_method_get() - Process a received management datagram.
+ * @sp: source port through which the MAD has been received.
+ * @rq_mad: received MAD.
+ * @rsp_mad: response MAD.
+ */
+static void srpt_mgmt_method_get(struct srpt_port *sp, struct ib_mad *rq_mad,
+ struct ib_dm_mad *rsp_mad)
+{
+ u16 attr_id;
+ u32 slot;
+ u8 hi, lo;
+
+ attr_id = be16_to_cpu(rq_mad->mad_hdr.attr_id);
+ switch (attr_id) {
+ case DM_ATTR_CLASS_PORT_INFO:
+ srpt_get_class_port_info(rsp_mad);
+ break;
+ case DM_ATTR_IOU_INFO:
+ srpt_get_iou(rsp_mad);
+ break;
+ case DM_ATTR_IOC_PROFILE:
+ slot = be32_to_cpu(rq_mad->mad_hdr.attr_mod);
+ srpt_get_ioc(sp, slot, rsp_mad);
+ break;
+ case DM_ATTR_SVC_ENTRIES:
+ slot = be32_to_cpu(rq_mad->mad_hdr.attr_mod);
+ hi = (u8) ((slot >> 8) & 0xff);
+ lo = (u8) (slot & 0xff);
+ slot = (u16) ((slot >> 16) & 0xffff);
+ srpt_get_svc_entries(srpt_service_guid,
+ slot, hi, lo, rsp_mad);
+ break;
+ default:
+ rsp_mad->mad_hdr.status =
+ __constant_cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD_ATTR);
+ break;
+ }
+}
+
+/**
+ * srpt_mad_send_handler() - Post MAD-send callback function.
+ */
+static void srpt_mad_send_handler(struct ib_mad_agent *mad_agent,
+ struct ib_mad_send_wc *mad_wc)
+{
+ ib_destroy_ah(mad_wc->send_buf->ah);
+ ib_free_send_mad(mad_wc->send_buf);
+}
+
+/**
+ * srpt_mad_recv_handler() - MAD reception callback function.
+ */
+static void srpt_mad_recv_handler(struct ib_mad_agent *mad_agent,
+ struct ib_mad_recv_wc *mad_wc)
+{
+ struct srpt_port *sport = (struct srpt_port *)mad_agent->context;
+ struct ib_ah *ah;
+ struct ib_mad_send_buf *rsp;
+ struct ib_dm_mad *dm_mad;
+
+ if (!mad_wc || !mad_wc->recv_buf.mad)
+ return;
+
+ ah = ib_create_ah_from_wc(mad_agent->qp->pd, mad_wc->wc,
+ mad_wc->recv_buf.grh, mad_agent->port_num);
+ if (IS_ERR(ah))
+ goto err;
+
+ BUILD_BUG_ON(offsetof(struct ib_dm_mad, data) != IB_MGMT_DEVICE_HDR);
+
+ rsp = ib_create_send_mad(mad_agent, mad_wc->wc->src_qp,
+ mad_wc->wc->pkey_index, 0,
+ IB_MGMT_DEVICE_HDR, IB_MGMT_DEVICE_DATA,
+ GFP_KERNEL);
+ if (IS_ERR(rsp))
+ goto err_rsp;
+
+ rsp->ah = ah;
+
+ dm_mad = rsp->mad;
+ memcpy(dm_mad, mad_wc->recv_buf.mad, sizeof *dm_mad);
+ dm_mad->mad_hdr.method = IB_MGMT_METHOD_GET_RESP;
+ dm_mad->mad_hdr.status = 0;
+
+ switch (mad_wc->recv_buf.mad->mad_hdr.method) {
+ case IB_MGMT_METHOD_GET:
+ srpt_mgmt_method_get(sport, mad_wc->recv_buf.mad, dm_mad);
+ break;
+ case IB_MGMT_METHOD_SET:
+ dm_mad->mad_hdr.status =
+ __constant_cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD_ATTR);
+ break;
+ default:
+ dm_mad->mad_hdr.status =
+ __constant_cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD);
+ break;
+ }
+
+ if (!ib_post_send_mad(rsp, NULL)) {
+ ib_free_recv_mad(mad_wc);
+ /* will destroy_ah & free_send_mad in send completion */
+ return;
+ }
+
+ ib_free_send_mad(rsp);
+
+err_rsp:
+ ib_destroy_ah(ah);
+err:
+ ib_free_recv_mad(mad_wc);
+}
+
+/**
+ * srpt_refresh_port() - Configure a HCA port.
+ *
+ * Enable InfiniBand management datagram processing, update the cached sm_lid,
+ * lid and gid values, and register a callback function for processing MADs
+ * on the specified port.
+ *
+ * Note: It is safe to call this function more than once for the same port.
+ */
+static int srpt_refresh_port(struct srpt_port *sport)
+{
+ struct ib_mad_reg_req reg_req;
+ struct ib_port_modify port_modify;
+ struct ib_port_attr port_attr;
+ int ret;
+
+ memset(&port_modify, 0, sizeof port_modify);
+ port_modify.set_port_cap_mask = IB_PORT_DEVICE_MGMT_SUP;
+ port_modify.clr_port_cap_mask = 0;
+
+ ret = ib_modify_port(sport->sdev->device, sport->port, 0, &port_modify);
+ if (ret)
+ goto err_mod_port;
+
+ ret = ib_query_port(sport->sdev->device, sport->port, &port_attr);
+ if (ret)
+ goto err_query_port;
+
+ sport->sm_lid = port_attr.sm_lid;
+ sport->lid = port_attr.lid;
+
+ ret = ib_query_gid(sport->sdev->device, sport->port, 0, &sport->gid);
+ if (ret)
+ goto err_query_port;
+
+ if (!sport->mad_agent) {
+ memset(&reg_req, 0, sizeof reg_req);
+ reg_req.mgmt_class = IB_MGMT_CLASS_DEVICE_MGMT;
+ reg_req.mgmt_class_version = IB_MGMT_BASE_VERSION;
+ set_bit(IB_MGMT_METHOD_GET, reg_req.method_mask);
+ set_bit(IB_MGMT_METHOD_SET, reg_req.method_mask);
+
+ sport->mad_agent = ib_register_mad_agent(sport->sdev->device,
+ sport->port,
+ IB_QPT_GSI,
+ &reg_req, 0,
+ srpt_mad_send_handler,
+ srpt_mad_recv_handler,
+ sport);
+ if (IS_ERR(sport->mad_agent)) {
+ ret = PTR_ERR(sport->mad_agent);
+ sport->mad_agent = NULL;
+ goto err_query_port;
+ }
+ }
+
+ return 0;
+
+err_query_port:
+
+ port_modify.set_port_cap_mask = 0;
+ port_modify.clr_port_cap_mask = IB_PORT_DEVICE_MGMT_SUP;
+ ib_modify_port(sport->sdev->device, sport->port, 0, &port_modify);
+
+err_mod_port:
+
+ return ret;
+}
+
+/**
+ * srpt_unregister_mad_agent() - Unregister MAD callback functions.
+ *
+ * Note: It is safe to call this function more than once for the same device.
+ */
+static void srpt_unregister_mad_agent(struct srpt_device *sdev)
+{
+ struct ib_port_modify port_modify = {
+ .clr_port_cap_mask = IB_PORT_DEVICE_MGMT_SUP,
+ };
+ struct srpt_port *sport;
+ int i;
+
+ for (i = 1; i <= sdev->device->phys_port_cnt; i++) {
+ sport = &sdev->port[i - 1];
+ WARN_ON(sport->port != i);
+ if (ib_modify_port(sdev->device, i, 0, &port_modify) < 0)
+ printk(KERN_ERR "disabling MAD processing failed.\n");
+ if (sport->mad_agent) {
+ ib_unregister_mad_agent(sport->mad_agent);
+ sport->mad_agent = NULL;
+ }
+ }
+}
+
+/**
+ * srpt_alloc_ioctx() - Allocate an SRPT I/O context structure.
+ */
+static struct srpt_ioctx *srpt_alloc_ioctx(struct srpt_device *sdev,
+ int ioctx_size, int dma_size,
+ enum dma_data_direction dir)
+{
+ struct srpt_ioctx *ioctx;
+
+ ioctx = kmalloc(ioctx_size, GFP_KERNEL);
+ if (!ioctx)
+ goto err;
+
+ ioctx->buf = kmalloc(dma_size, GFP_KERNEL);
+ if (!ioctx->buf)
+ goto err_free_ioctx;
+
+ ioctx->dma = ib_dma_map_single(sdev->device, ioctx->buf, dma_size, dir);
+ if (ib_dma_mapping_error(sdev->device, ioctx->dma))
+ goto err_free_buf;
+
+ return ioctx;
+
+err_free_buf:
+ kfree(ioctx->buf);
+err_free_ioctx:
+ kfree(ioctx);
+err:
+ return NULL;
+}
+
+/**
+ * srpt_free_ioctx() - Free an SRPT I/O context structure.
+ */
+static void srpt_free_ioctx(struct srpt_device *sdev, struct srpt_ioctx *ioctx,
+ int dma_size, enum dma_data_direction dir)
+{
+ if (!ioctx)
+ return;
+
+ ib_dma_unmap_single(sdev->device, ioctx->dma, dma_size, dir);
+ kfree(ioctx->buf);
+ kfree(ioctx);
+}
+
+/**
+ * srpt_alloc_ioctx_ring() - Allocate a ring of SRPT I/O context structures.
+ * @sdev: Device to allocate the I/O context ring for.
+ * @ring_size: Number of elements in the I/O context ring.
+ * @ioctx_size: I/O context size.
+ * @dma_size: DMA buffer size.
+ * @dir: DMA data direction.
+ */
+static struct srpt_ioctx **srpt_alloc_ioctx_ring(struct srpt_device *sdev,
+ int ring_size, int ioctx_size,
+ int dma_size, enum dma_data_direction dir)
+{
+ struct srpt_ioctx **ring;
+ int i;
+
+ WARN_ON(ioctx_size != sizeof(struct srpt_recv_ioctx)
+ && ioctx_size != sizeof(struct srpt_send_ioctx));
+
+ ring = kmalloc(ring_size * sizeof(ring[0]), GFP_KERNEL);
+ if (!ring)
+ goto out;
+ for (i = 0; i < ring_size; ++i) {
+ ring[i] = srpt_alloc_ioctx(sdev, ioctx_size, dma_size, dir);
+ if (!ring[i])
+ goto err;
+ ring[i]->index = i;
+ }
+ goto out;
+
+err:
+ while (--i >= 0)
+ srpt_free_ioctx(sdev, ring[i], dma_size, dir);
+ kfree(ring);
+out:
+ return ring;
+}
+
+/**
+ * srpt_free_ioctx_ring() - Free the ring of SRPT I/O context structures.
+ */
+static void srpt_free_ioctx_ring(struct srpt_ioctx **ioctx_ring,
+ struct srpt_device *sdev, int ring_size,
+ int dma_size, enum dma_data_direction dir)
+{
+ int i;
+
+ for (i = 0; i < ring_size; ++i)
+ srpt_free_ioctx(sdev, ioctx_ring[i], dma_size, dir);
+ kfree(ioctx_ring);
+}
+
+/**
+ * srpt_get_cmd_state() - Get the state of a SCSI command.
+ */
+static enum srpt_command_state srpt_get_cmd_state(struct srpt_send_ioctx *ioctx)
+{
+ enum srpt_command_state state;
+ unsigned long flags;
+
+ BUG_ON(!ioctx);
+
+ spin_lock_irqsave(&ioctx->spinlock, flags);
+ state = ioctx->state;
+ spin_unlock_irqrestore(&ioctx->spinlock, flags);
+ return state;
+}
+
+/**
+ * srpt_set_cmd_state() - Set the state of a SCSI command.
+ *
+ * Does not modify the state of aborted commands. Returns the previous command
+ * state.
+ */
+static enum srpt_command_state srpt_set_cmd_state(struct srpt_send_ioctx *ioctx,
+ enum srpt_command_state new)
+{
+ enum srpt_command_state previous;
+ unsigned long flags;
+
+ BUG_ON(!ioctx);
+
+ spin_lock_irqsave(&ioctx->spinlock, flags);
+ previous = ioctx->state;
+ if (previous != SRPT_STATE_DONE)
+ ioctx->state = new;
+ spin_unlock_irqrestore(&ioctx->spinlock, flags);
+
+ return previous;
+}
+
+/**
+ * srpt_test_and_set_cmd_state() - Test and set the state of a command.
+ *
+ * Returns true if and only if the previous command state was equal to 'old'.
+ */
+static bool srpt_test_and_set_cmd_state(struct srpt_send_ioctx *ioctx,
+ enum srpt_command_state old,
+ enum srpt_command_state new)
+{
+ enum srpt_command_state previous;
+ unsigned long flags;
+
+ WARN_ON(!ioctx);
+ WARN_ON(old == SRPT_STATE_DONE);
+ WARN_ON(new == SRPT_STATE_NEW);
+
+ spin_lock_irqsave(&ioctx->spinlock, flags);
+ previous = ioctx->state;
+ if (previous == old)
+ ioctx->state = new;
+ spin_unlock_irqrestore(&ioctx->spinlock, flags);
+ return previous == old;
+}
+
+/**
+ * srpt_post_recv() - Post an IB receive request.
+ */
+static int srpt_post_recv(struct srpt_device *sdev,
+ struct srpt_recv_ioctx *ioctx)
+{
+ struct ib_sge list;
+ struct ib_recv_wr wr, *bad_wr;
+
+ BUG_ON(!sdev);
+ wr.wr_id = encode_wr_id(SRPT_RECV, ioctx->ioctx.index);
+
+ list.addr = ioctx->ioctx.dma;
+ list.length = srp_max_req_size;
+ list.lkey = sdev->mr->lkey;
+
+ wr.next = NULL;
+ wr.sg_list = &list;
+ wr.num_sge = 1;
+
+ return ib_post_srq_recv(sdev->srq, &wr, &bad_wr);
+}
+
+/**
+ * srpt_post_send() - Post an IB send request.
+ *
+ * Returns zero upon success and a non-zero value upon failure.
+ */
+static int srpt_post_send(struct srpt_rdma_ch *ch,
+ struct srpt_send_ioctx *ioctx, int len)
+{
+ struct ib_sge list;
+ struct ib_send_wr wr, *bad_wr;
+ struct srpt_device *sdev = ch->sport->sdev;
+ int ret;
+
+ atomic_inc(&ch->req_lim);
+
+ ret = -ENOMEM;
+ if (unlikely(atomic_dec_return(&ch->sq_wr_avail) < 0)) {
+ printk(KERN_WARNING "IB send queue full (needed 1)\n");
+ goto out;
+ }
+
+ ib_dma_sync_single_for_device(sdev->device, ioctx->ioctx.dma, len,
+ DMA_TO_DEVICE);
+
+ list.addr = ioctx->ioctx.dma;
+ list.length = len;
+ list.lkey = sdev->mr->lkey;
+
+ wr.next = NULL;
+ wr.wr_id = encode_wr_id(SRPT_SEND, ioctx->ioctx.index);
+ wr.sg_list = &list;
+ wr.num_sge = 1;
+ wr.opcode = IB_WR_SEND;
+ wr.send_flags = IB_SEND_SIGNALED;
+
+ ret = ib_post_send(ch->qp, &wr, &bad_wr);
+
+out:
+ if (ret < 0) {
+ atomic_inc(&ch->sq_wr_avail);
+ atomic_dec(&ch->req_lim);
+ }
+ return ret;
+}
+
+/**
+ * srpt_get_desc_tbl() - Parse the data descriptors of an SRP_CMD request.
+ * @ioctx: Pointer to the I/O context associated with the request.
+ * @srp_cmd: Pointer to the SRP_CMD request data.
+ * @dir: Pointer to the variable to which the transfer direction will be
+ * written.
+ * @data_len: Pointer to the variable to which the total data length of all
+ * descriptors in the SRP_CMD request will be written.
+ *
+ * This function initializes ioctx->nrbuf and ioctx->r_bufs.
+ *
+ * Returns -EINVAL when the SRP_CMD request contains inconsistent descriptors;
+ * -ENOMEM when memory allocation fails and zero upon success.
+ */
+static int srpt_get_desc_tbl(struct srpt_send_ioctx *ioctx,
+ struct srp_cmd *srp_cmd,
+ enum dma_data_direction *dir, u64 *data_len)
+{
+ struct srp_indirect_buf *idb;
+ struct srp_direct_buf *db;
+ unsigned add_cdb_offset;
+ int ret;
+
+ /*
+ * The pointer computations below will only be compiled correctly
+ * if srp_cmd::add_data is declared as s8*, u8*, s8[] or u8[], so check
+ * whether srp_cmd::add_data has been declared as a byte pointer.
+ */
+ BUILD_BUG_ON(!__same_type(srp_cmd->add_data[0], (s8)0)
+ && !__same_type(srp_cmd->add_data[0], (u8)0));
+
+ BUG_ON(!dir);
+ BUG_ON(!data_len);
+
+ ret = 0;
+ *data_len = 0;
+
+ /*
+ * The lower four bits of the buffer format field contain the DATA-IN
+ * buffer descriptor format, and the highest four bits contain the
+ * DATA-OUT buffer descriptor format.
+ */
+ *dir = DMA_NONE;
+ if (srp_cmd->buf_fmt & 0xf)
+ /* DATA-IN: transfer data from target to initiator (read). */
+ *dir = DMA_FROM_DEVICE;
+ else if (srp_cmd->buf_fmt >> 4)
+ /* DATA-OUT: transfer data from initiator to target (write). */
+ *dir = DMA_TO_DEVICE;
+
+ /*
+ * According to the SRP spec, the lower two bits of the 'ADDITIONAL
+ * CDB LENGTH' field are reserved and the size in bytes of this field
+ * is four times the value specified in bits 3..7. Hence the "& ~3".
+ */
+ add_cdb_offset = srp_cmd->add_cdb_len & ~3;
+ if (((srp_cmd->buf_fmt & 0xf) == SRP_DATA_DESC_DIRECT) ||
+ ((srp_cmd->buf_fmt >> 4) == SRP_DATA_DESC_DIRECT)) {
+ ioctx->n_rbuf = 1;
+ ioctx->rbufs = &ioctx->single_rbuf;
+
+ db = (struct srp_direct_buf *)(srp_cmd->add_data
+ + add_cdb_offset);
+ memcpy(ioctx->rbufs, db, sizeof *db);
+ *data_len = be32_to_cpu(db->len);
+ } else if (((srp_cmd->buf_fmt & 0xf) == SRP_DATA_DESC_INDIRECT) ||
+ ((srp_cmd->buf_fmt >> 4) == SRP_DATA_DESC_INDIRECT)) {
+ idb = (struct srp_indirect_buf *)(srp_cmd->add_data
+ + add_cdb_offset);
+
+ ioctx->n_rbuf = be32_to_cpu(idb->table_desc.len) / sizeof *db;
+
+ if (ioctx->n_rbuf >
+ (srp_cmd->data_out_desc_cnt + srp_cmd->data_in_desc_cnt)) {
+ printk(KERN_ERR "received unsupported SRP_CMD request"
+ " type (%u out + %u in != %u / %zu)\n",
+ srp_cmd->data_out_desc_cnt,
+ srp_cmd->data_in_desc_cnt,
+ be32_to_cpu(idb->table_desc.len),
+ sizeof(*db));
+ ioctx->n_rbuf = 0;
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (ioctx->n_rbuf == 1)
+ ioctx->rbufs = &ioctx->single_rbuf;
+ else {
+ ioctx->rbufs =
+ kmalloc(ioctx->n_rbuf * sizeof *db, GFP_ATOMIC);
+ if (!ioctx->rbufs) {
+ ioctx->n_rbuf = 0;
+ ret = -ENOMEM;
+ goto out;
+ }
+ }
+
+ db = idb->desc_list;
+ memcpy(ioctx->rbufs, db, ioctx->n_rbuf * sizeof *db);
+ *data_len = be32_to_cpu(idb->len);
+ }
+out:
+ return ret;
+}
+
+/**
+ * srpt_init_ch_qp() - Initialize queue pair attributes.
+ *
+ * Initialized the attributes of queue pair 'qp' by allowing local write,
+ * remote read and remote write. Also transitions 'qp' to state IB_QPS_INIT.
+ */
+static int srpt_init_ch_qp(struct srpt_rdma_ch *ch, struct ib_qp *qp)
+{
+ struct ib_qp_attr *attr;
+ int ret;
+
+ attr = kzalloc(sizeof *attr, GFP_KERNEL);
+ if (!attr)
+ return -ENOMEM;
+
+ attr->qp_state = IB_QPS_INIT;
+ attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE | IB_ACCESS_REMOTE_READ |
+ IB_ACCESS_REMOTE_WRITE;
+ attr->port_num = ch->sport->port;
+ attr->pkey_index = 0;
+
+ ret = ib_modify_qp(qp, attr,
+ IB_QP_STATE | IB_QP_ACCESS_FLAGS | IB_QP_PORT |
+ IB_QP_PKEY_INDEX);
+
+ kfree(attr);
+ return ret;
+}
+
+/**
+ * srpt_ch_qp_rtr() - Change the state of a channel to 'ready to receive' (RTR).
+ * @ch: channel of the queue pair.
+ * @qp: queue pair to change the state of.
+ *
+ * Returns zero upon success and a negative value upon failure.
+ *
+ * Note: currently a struct ib_qp_attr takes 136 bytes on a 64-bit system.
+ * If this structure ever becomes larger, it might be necessary to allocate
+ * it dynamically instead of on the stack.
+ */
+static int srpt_ch_qp_rtr(struct srpt_rdma_ch *ch, struct ib_qp *qp)
+{
+ struct ib_qp_attr qp_attr;
+ int attr_mask;
+ int ret;
+
+ qp_attr.qp_state = IB_QPS_RTR;
+ ret = ib_cm_init_qp_attr(ch->cm_id, &qp_attr, &attr_mask);
+ if (ret)
+ goto out;
+
+ qp_attr.max_dest_rd_atomic = 4;
+
+ ret = ib_modify_qp(qp, &qp_attr, attr_mask);
+
+out:
+ return ret;
+}
+
+/**
+ * srpt_ch_qp_rts() - Change the state of a channel to 'ready to send' (RTS).
+ * @ch: channel of the queue pair.
+ * @qp: queue pair to change the state of.
+ *
+ * Returns zero upon success and a negative value upon failure.
+ *
+ * Note: currently a struct ib_qp_attr takes 136 bytes on a 64-bit system.
+ * If this structure ever becomes larger, it might be necessary to allocate
+ * it dynamically instead of on the stack.
+ */
+static int srpt_ch_qp_rts(struct srpt_rdma_ch *ch, struct ib_qp *qp)
+{
+ struct ib_qp_attr qp_attr;
+ int attr_mask;
+ int ret;
+
+ qp_attr.qp_state = IB_QPS_RTS;
+ ret = ib_cm_init_qp_attr(ch->cm_id, &qp_attr, &attr_mask);
+ if (ret)
+ goto out;
+
+ qp_attr.max_rd_atomic = 4;
+
+ ret = ib_modify_qp(qp, &qp_attr, attr_mask);
+
+out:
+ return ret;
+}
+
+/**
+ * srpt_ch_qp_err() - Set the channel queue pair state to 'error'.
+ */
+static int srpt_ch_qp_err(struct srpt_rdma_ch *ch)
+{
+ struct ib_qp_attr qp_attr;
+
+ qp_attr.qp_state = IB_QPS_ERR;
+ return ib_modify_qp(ch->qp, &qp_attr, IB_QP_STATE);
+}
+
+/**
+ * srpt_unmap_sg_to_ib_sge() - Unmap an IB SGE list.
+ */
+static void srpt_unmap_sg_to_ib_sge(struct srpt_rdma_ch *ch,
+ struct srpt_send_ioctx *ioctx)
+{
+ struct scatterlist *sg;
+ enum dma_data_direction dir;
+
+ BUG_ON(!ch);
+ BUG_ON(!ioctx);
+ BUG_ON(ioctx->n_rdma && !ioctx->rdma_ius);
+
+ while (ioctx->n_rdma)
+ kfree(ioctx->rdma_ius[--ioctx->n_rdma].sge);
+
+ kfree(ioctx->rdma_ius);
+ ioctx->rdma_ius = NULL;
+
+ if (ioctx->mapped_sg_count) {
+ sg = ioctx->sg;
+ WARN_ON(!sg);
+ dir = ioctx->cmd.data_direction;
+ BUG_ON(dir == DMA_NONE);
+ ib_dma_unmap_sg(ch->sport->sdev->device, sg, ioctx->sg_cnt,
+ opposite_dma_dir(dir));
+ ioctx->mapped_sg_count = 0;
+ }
+}
+
+/**
+ * srpt_map_sg_to_ib_sge() - Map an SG list to an IB SGE list.
+ */
+static int srpt_map_sg_to_ib_sge(struct srpt_rdma_ch *ch,
+ struct srpt_send_ioctx *ioctx)
+{
+ struct se_cmd *cmd;
+ struct scatterlist *sg, *sg_orig;
+ int sg_cnt;
+ enum dma_data_direction dir;
+ struct rdma_iu *riu;
+ struct srp_direct_buf *db;
+ dma_addr_t dma_addr;
+ struct ib_sge *sge;
+ u64 raddr;
+ u32 rsize;
+ u32 tsize;
+ u32 dma_len;
+ int count, nrdma;
+ int i, j, k;
+
+ BUG_ON(!ch);
+ BUG_ON(!ioctx);
+ cmd = &ioctx->cmd;
+ dir = cmd->data_direction;
+ BUG_ON(dir == DMA_NONE);
+
+ transport_do_task_sg_chain(cmd);
+ ioctx->sg = sg = sg_orig = cmd->t_tasks_sg_chained;
+ ioctx->sg_cnt = sg_cnt = cmd->t_tasks_sg_chained_no;
+
+ count = ib_dma_map_sg(ch->sport->sdev->device, sg, sg_cnt,
+ opposite_dma_dir(dir));
+ if (unlikely(!count))
+ return -EAGAIN;
+
+ ioctx->mapped_sg_count = count;
+
+ if (ioctx->rdma_ius && ioctx->n_rdma_ius)
+ nrdma = ioctx->n_rdma_ius;
+ else {
+ nrdma = (count + SRPT_DEF_SG_PER_WQE - 1) / SRPT_DEF_SG_PER_WQE
+ + ioctx->n_rbuf;
+
+ ioctx->rdma_ius = kzalloc(nrdma * sizeof *riu, GFP_KERNEL);
+ if (!ioctx->rdma_ius)
+ goto free_mem;
+
+ ioctx->n_rdma_ius = nrdma;
+ }
+
+ db = ioctx->rbufs;
+ tsize = cmd->data_length;
+ dma_len = sg_dma_len(&sg[0]);
+ riu = ioctx->rdma_ius;
+
+ /*
+ * For each remote desc - calculate the #ib_sge.
+ * If #ib_sge < SRPT_DEF_SG_PER_WQE per rdma operation then
+ * each remote desc rdma_iu is required a rdma wr;
+ * else
+ * we need to allocate extra rdma_iu to carry extra #ib_sge in
+ * another rdma wr
+ */
+ for (i = 0, j = 0;
+ j < count && i < ioctx->n_rbuf && tsize > 0; ++i, ++riu, ++db) {
+ rsize = be32_to_cpu(db->len);
+ raddr = be64_to_cpu(db->va);
+ riu->raddr = raddr;
+ riu->rkey = be32_to_cpu(db->key);
+ riu->sge_cnt = 0;
+
+ /* calculate how many sge required for this remote_buf */
+ while (rsize > 0 && tsize > 0) {
+
+ if (rsize >= dma_len) {
+ tsize -= dma_len;
+ rsize -= dma_len;
+ raddr += dma_len;
+
+ if (tsize > 0) {
+ ++j;
+ if (j < count) {
+ sg = sg_next(sg);
+ dma_len = sg_dma_len(sg);
+ }
+ }
+ } else {
+ tsize -= rsize;
+ dma_len -= rsize;
+ rsize = 0;
+ }
+
+ ++riu->sge_cnt;
+
+ if (rsize > 0 && riu->sge_cnt == SRPT_DEF_SG_PER_WQE) {
+ ++ioctx->n_rdma;
+ riu->sge =
+ kmalloc(riu->sge_cnt * sizeof *riu->sge,
+ GFP_KERNEL);
+ if (!riu->sge)
+ goto free_mem;
+
+ ++riu;
+ riu->sge_cnt = 0;
+ riu->raddr = raddr;
+ riu->rkey = be32_to_cpu(db->key);
+ }
+ }
+
+ ++ioctx->n_rdma;
+ riu->sge = kmalloc(riu->sge_cnt * sizeof *riu->sge,
+ GFP_KERNEL);
+ if (!riu->sge)
+ goto free_mem;
+ }
+
+ db = ioctx->rbufs;
+ tsize = cmd->data_length;
+ riu = ioctx->rdma_ius;
+ sg = sg_orig;
+ dma_len = sg_dma_len(&sg[0]);
+ dma_addr = sg_dma_address(&sg[0]);
+
+ /* this second loop is really mapped sg_addres to rdma_iu->ib_sge */
+ for (i = 0, j = 0;
+ j < count && i < ioctx->n_rbuf && tsize > 0; ++i, ++riu, ++db) {
+ rsize = be32_to_cpu(db->len);
+ sge = riu->sge;
+ k = 0;
+
+ while (rsize > 0 && tsize > 0) {
+ sge->addr = dma_addr;
+ sge->lkey = ch->sport->sdev->mr->lkey;
+
+ if (rsize >= dma_len) {
+ sge->length =
+ (tsize < dma_len) ? tsize : dma_len;
+ tsize -= dma_len;
+ rsize -= dma_len;
+
+ if (tsize > 0) {
+ ++j;
+ if (j < count) {
+ sg = sg_next(sg);
+ dma_len = sg_dma_len(sg);
+ dma_addr = sg_dma_address(sg);
+ }
+ }
+ } else {
+ sge->length = (tsize < rsize) ? tsize : rsize;
+ tsize -= rsize;
+ dma_len -= rsize;
+ dma_addr += rsize;
+ rsize = 0;
+ }
+
+ ++k;
+ if (k == riu->sge_cnt && rsize > 0 && tsize > 0) {
+ ++riu;
+ sge = riu->sge;
+ k = 0;
+ } else if (rsize > 0 && tsize > 0)
+ ++sge;
+ }
+ }
+
+ return 0;
+
+free_mem:
+ srpt_unmap_sg_to_ib_sge(ch, ioctx);
+
+ return -ENOMEM;
+}
+
+/**
+ * srpt_get_send_ioctx() - Obtain an I/O context for sending to the initiator.
+ */
+static struct srpt_send_ioctx *srpt_get_send_ioctx(struct srpt_rdma_ch *ch)
+{
+ struct srpt_send_ioctx *ioctx;
+ unsigned long flags;
+
+ BUG_ON(!ch);
+
+ ioctx = NULL;
+ spin_lock_irqsave(&ch->spinlock, flags);
+ if (!list_empty(&ch->free_list)) {
+ ioctx = list_first_entry(&ch->free_list,
+ struct srpt_send_ioctx, free_list);
+ list_del(&ioctx->free_list);
+ }
+ spin_unlock_irqrestore(&ch->spinlock, flags);
+
+ if (!ioctx)
+ return ioctx;
+
+ BUG_ON(ioctx->ch != ch);
+ kref_init(&ioctx->kref);
+ spin_lock_init(&ioctx->spinlock);
+ ioctx->state = SRPT_STATE_NEW;
+ ioctx->n_rbuf = 0;
+ ioctx->rbufs = NULL;
+ ioctx->n_rdma = 0;
+ ioctx->n_rdma_ius = 0;
+ ioctx->rdma_ius = NULL;
+ ioctx->mapped_sg_count = 0;
+ init_completion(&ioctx->tx_done);
+ ioctx->queue_status_only = false;
+ /*
+ * transport_init_se_cmd() does not initialize all fields, so do it
+ * here.
+ */
+ memset(&ioctx->cmd, 0, sizeof(ioctx->cmd));
+ memset(&ioctx->sense_data, 0, sizeof(ioctx->sense_data));
+
+ return ioctx;
+}
+
+/**
+ * srpt_put_send_ioctx() - Free up resources.
+ */
+static void srpt_put_send_ioctx(struct srpt_send_ioctx *ioctx)
+{
+ struct srpt_rdma_ch *ch;
+ unsigned long flags;
+
+ BUG_ON(!ioctx);
+ ch = ioctx->ch;
+ BUG_ON(!ch);
+
+ WARN_ON(srpt_get_cmd_state(ioctx) != SRPT_STATE_DONE);
+
+ srpt_unmap_sg_to_ib_sge(ioctx->ch, ioctx);
+ transport_generic_free_cmd(&ioctx->cmd, 0);
+
+ if (ioctx->n_rbuf > 1) {
+ kfree(ioctx->rbufs);
+ ioctx->rbufs = NULL;
+ ioctx->n_rbuf = 0;
+ }
+
+ spin_lock_irqsave(&ch->spinlock, flags);
+ list_add(&ioctx->free_list, &ch->free_list);
+ spin_unlock_irqrestore(&ch->spinlock, flags);
+}
+
+static void srpt_put_send_ioctx_kref(struct kref *kref)
+{
+ srpt_put_send_ioctx(container_of(kref, struct srpt_send_ioctx, kref));
+}
+
+/**
+ * srpt_abort_cmd() - Abort a SCSI command.
+ * @ioctx: I/O context associated with the SCSI command.
+ * @context: Preferred execution context.
+ */
+static int srpt_abort_cmd(struct srpt_send_ioctx *ioctx)
+{
+ enum srpt_command_state state;
+ unsigned long flags;
+
+ BUG_ON(!ioctx);
+
+ /*
+ * If the command is in a state where the target core is waiting for
+ * the ib_srpt driver, change the state to the next state. Changing
+ * the state of the command from SRPT_STATE_NEED_DATA to
+ * SRPT_STATE_DATA_IN ensures that srpt_xmit_response() will call this
+ * function a second time.
+ */
+
+ spin_lock_irqsave(&ioctx->spinlock, flags);
+ state = ioctx->state;
+ switch (state) {
+ case SRPT_STATE_NEED_DATA:
+ ioctx->state = SRPT_STATE_DATA_IN;
+ break;
+ case SRPT_STATE_DATA_IN:
+ case SRPT_STATE_CMD_RSP_SENT:
+ case SRPT_STATE_MGMT_RSP_SENT:
+ ioctx->state = SRPT_STATE_DONE;
+ break;
+ default:
+ break;
+ }
+ spin_unlock_irqrestore(&ioctx->spinlock, flags);
+
+ if (state == SRPT_STATE_DONE)
+ goto out;
+
+ pr_debug("Aborting cmd with state %d and tag %lld\n", state,
+ ioctx->tag);
+
+ switch (state) {
+ case SRPT_STATE_NEW:
+ case SRPT_STATE_DATA_IN:
+ case SRPT_STATE_MGMT:
+ /*
+ * Do nothing - defer abort processing until
+ * srpt_queue_response() is invoked.
+ */
+ WARN_ON(!transport_check_aborted_status(&ioctx->cmd, false));
+ break;
+ case SRPT_STATE_NEED_DATA:
+ /* DMA_TO_DEVICE (write) - RDMA read error. */
+ atomic_set(&ioctx->cmd.transport_lun_stop, 1);
+ transport_generic_handle_data(&ioctx->cmd);
+ break;
+ case SRPT_STATE_CMD_RSP_SENT:
+ /*
+ * SRP_RSP sending failed or the SRP_RSP send completion has
+ * not been received in time.
+ */
+ srpt_unmap_sg_to_ib_sge(ioctx->ch, ioctx);
+ atomic_set(&ioctx->cmd.transport_lun_stop, 1);
+ kref_put(&ioctx->kref, srpt_put_send_ioctx_kref);
+ break;
+ case SRPT_STATE_MGMT_RSP_SENT:
+ srpt_set_cmd_state(ioctx, SRPT_STATE_DONE);
+ kref_put(&ioctx->kref, srpt_put_send_ioctx_kref);
+ break;
+ default:
+ WARN_ON("ERROR: unexpected command state");
+ break;
+ }
+
+out:
+ return state;
+}
+
+/**
+ * srpt_handle_send_err_comp() - Process an IB_WC_SEND error completion.
+ */
+static void srpt_handle_send_err_comp(struct srpt_rdma_ch *ch, u64 wr_id)
+{
+ struct srpt_send_ioctx *ioctx;
+ enum srpt_command_state state;
+ struct se_cmd *cmd;
+ u32 index;
+
+ atomic_inc(&ch->sq_wr_avail);
+
+ index = idx_from_wr_id(wr_id);
+ ioctx = ch->ioctx_ring[index];
+ state = srpt_get_cmd_state(ioctx);
+ cmd = &ioctx->cmd;
+
+ WARN_ON(state != SRPT_STATE_CMD_RSP_SENT
+ && state != SRPT_STATE_MGMT_RSP_SENT
+ && state != SRPT_STATE_NEED_DATA
+ && state != SRPT_STATE_DONE);
+
+ /* If SRP_RSP sending failed, undo the ch->req_lim change. */
+ if (state == SRPT_STATE_CMD_RSP_SENT
+ || state == SRPT_STATE_MGMT_RSP_SENT)
+ atomic_dec(&ch->req_lim);
+
+ srpt_abort_cmd(ioctx);
+}
+
+/**
+ * srpt_handle_send_comp() - Process an IB send completion notification.
+ */
+static void srpt_handle_send_comp(struct srpt_rdma_ch *ch,
+ struct srpt_send_ioctx *ioctx)
+{
+ enum srpt_command_state state;
+
+ atomic_inc(&ch->sq_wr_avail);
+
+ state = srpt_set_cmd_state(ioctx, SRPT_STATE_DONE);
+
+ if (WARN_ON(state != SRPT_STATE_CMD_RSP_SENT
+ && state != SRPT_STATE_MGMT_RSP_SENT
+ && state != SRPT_STATE_DONE))
+ pr_debug("state = %d\n", state);
+
+ if (state != SRPT_STATE_DONE)
+ kref_put(&ioctx->kref, srpt_put_send_ioctx_kref);
+ else
+ printk(KERN_ERR "IB completion has been received too late for"
+ " wr_id = %u.\n", ioctx->ioctx.index);
+}
+
+/**
+ * srpt_handle_rdma_comp() - Process an IB RDMA completion notification.
+ *
+ * Note: transport_generic_handle_data() is asynchronous so unmapping the
+ * data that has been transferred via IB RDMA must be postponed until the
+ * check_stop_free() callback.
+ */
+static void srpt_handle_rdma_comp(struct srpt_rdma_ch *ch,
+ struct srpt_send_ioctx *ioctx,
+ enum srpt_opcode opcode)
+{
+ WARN_ON(ioctx->n_rdma <= 0);
+ atomic_add(ioctx->n_rdma, &ch->sq_wr_avail);
+
+ if (opcode == SRPT_RDMA_READ_LAST) {
+ if (srpt_test_and_set_cmd_state(ioctx, SRPT_STATE_NEED_DATA,
+ SRPT_STATE_DATA_IN))
+ transport_generic_handle_data(&ioctx->cmd);
+ else
+ printk(KERN_ERR "%s[%d]: wrong state = %d\n", __func__,
+ __LINE__, srpt_get_cmd_state(ioctx));
+ } else if (opcode == SRPT_RDMA_ABORT) {
+ ioctx->rdma_aborted = true;
+ } else {
+ WARN(true, "unexpected opcode %d\n", opcode);
+ }
+}
+
+/**
+ * srpt_handle_rdma_err_comp() - Process an IB RDMA error completion.
+ */
+static void srpt_handle_rdma_err_comp(struct srpt_rdma_ch *ch,
+ struct srpt_send_ioctx *ioctx,
+ enum srpt_opcode opcode)
+{
+ struct se_cmd *cmd;
+ enum srpt_command_state state;
+
+ cmd = &ioctx->cmd;
+ state = srpt_get_cmd_state(ioctx);
+ switch (opcode) {
+ case SRPT_RDMA_READ_LAST:
+ if (ioctx->n_rdma <= 0) {
+ printk(KERN_ERR "Received invalid RDMA read"
+ " error completion with idx %d\n",
+ ioctx->ioctx.index);
+ break;
+ }
+ atomic_add(ioctx->n_rdma, &ch->sq_wr_avail);
+ if (state == SRPT_STATE_NEED_DATA)
+ srpt_abort_cmd(ioctx);
+ else
+ printk(KERN_ERR "%s[%d]: wrong state = %d\n",
+ __func__, __LINE__, state);
+ break;
+ case SRPT_RDMA_WRITE_LAST:
+ atomic_set(&ioctx->cmd.transport_lun_stop, 1);
+ break;
+ default:
+ printk(KERN_ERR "%s[%d]: opcode = %u\n", __func__,
+ __LINE__, opcode);
+ break;
+ }
+}
+
+/**
+ * srpt_build_cmd_rsp() - Build an SRP_RSP response.
+ * @ch: RDMA channel through which the request has been received.
+ * @ioctx: I/O context associated with the SRP_CMD request. The response will
+ * be built in the buffer ioctx->buf points at and hence this function will
+ * overwrite the request data.
+ * @tag: tag of the request for which this response is being generated.
+ * @status: value for the STATUS field of the SRP_RSP information unit.
+ *
+ * Returns the size in bytes of the SRP_RSP response.
+ *
+ * An SRP_RSP response contains a SCSI status or service response. See also
+ * section 6.9 in the SRP r16a document for the format of an SRP_RSP
+ * response. See also SPC-2 for more information about sense data.
+ */
+static int srpt_build_cmd_rsp(struct srpt_rdma_ch *ch,
+ struct srpt_send_ioctx *ioctx, u64 tag,
+ int status)
+{
+ struct srp_rsp *srp_rsp;
+ const u8 *sense_data;
+ int sense_data_len, max_sense_len;
+
+ /*
+ * The lowest bit of all SAM-3 status codes is zero (see also
+ * paragraph 5.3 in SAM-3).
+ */
+ WARN_ON(status & 1);
+
+ srp_rsp = ioctx->ioctx.buf;
+ BUG_ON(!srp_rsp);
+
+ sense_data = ioctx->sense_data;
+ sense_data_len = ioctx->cmd.scsi_sense_length;
+ WARN_ON(sense_data_len > sizeof(ioctx->sense_data));
+
+ memset(srp_rsp, 0, sizeof *srp_rsp);
+ srp_rsp->opcode = SRP_RSP;
+ srp_rsp->req_lim_delta =
+ __constant_cpu_to_be32(1 + atomic_xchg(&ch->req_lim_delta, 0));
+ srp_rsp->tag = tag;
+ srp_rsp->status = status;
+
+ if (sense_data_len) {
+ BUILD_BUG_ON(MIN_MAX_RSP_SIZE <= sizeof(*srp_rsp));
+ max_sense_len = ch->max_ti_iu_len - sizeof(*srp_rsp);
+ if (sense_data_len > max_sense_len) {
+ printk(KERN_WARNING "truncated sense data from %d to %d"
+ " bytes\n", sense_data_len, max_sense_len);
+ sense_data_len = max_sense_len;
+ }
+
+ srp_rsp->flags |= SRP_RSP_FLAG_SNSVALID;
+ srp_rsp->sense_data_len = cpu_to_be32(sense_data_len);
+ memcpy(srp_rsp + 1, sense_data, sense_data_len);
+ }
+
+ return sizeof(*srp_rsp) + sense_data_len;
+}
+
+/**
+ * srpt_build_tskmgmt_rsp() - Build a task management response.
+ * @ch: RDMA channel through which the request has been received.
+ * @ioctx: I/O context in which the SRP_RSP response will be built.
+ * @rsp_code: RSP_CODE that will be stored in the response.
+ * @tag: Tag of the request for which this response is being generated.
+ *
+ * Returns the size in bytes of the SRP_RSP response.
+ *
+ * An SRP_RSP response contains a SCSI status or service response. See also
+ * section 6.9 in the SRP r16a document for the format of an SRP_RSP
+ * response.
+ */
+static int srpt_build_tskmgmt_rsp(struct srpt_rdma_ch *ch,
+ struct srpt_send_ioctx *ioctx,
+ u8 rsp_code, u64 tag)
+{
+ struct srp_rsp *srp_rsp;
+ int resp_data_len;
+ int resp_len;
+
+ resp_data_len = (rsp_code == SRP_TSK_MGMT_SUCCESS) ? 0 : 4;
+ resp_len = sizeof(*srp_rsp) + resp_data_len;
+
+ srp_rsp = ioctx->ioctx.buf;
+ BUG_ON(!srp_rsp);
+ memset(srp_rsp, 0, sizeof *srp_rsp);
+
+ srp_rsp->opcode = SRP_RSP;
+ srp_rsp->req_lim_delta = __constant_cpu_to_be32(1
+ + atomic_xchg(&ch->req_lim_delta, 0));
+ srp_rsp->tag = tag;
+
+ if (rsp_code != SRP_TSK_MGMT_SUCCESS) {
+ srp_rsp->flags |= SRP_RSP_FLAG_RSPVALID;
+ srp_rsp->resp_data_len = cpu_to_be32(resp_data_len);
+ srp_rsp->data[3] = rsp_code;
+ }
+
+ return resp_len;
+}
+
+#define NO_SUCH_LUN ((uint64_t)-1LL)
+
+/*
+ * SCSI LUN addressing method. See also SAM-2 and the section about
+ * eight byte LUNs.
+ */
+enum scsi_lun_addr_method {
+ SCSI_LUN_ADDR_METHOD_PERIPHERAL = 0,
+ SCSI_LUN_ADDR_METHOD_FLAT = 1,
+ SCSI_LUN_ADDR_METHOD_LUN = 2,
+ SCSI_LUN_ADDR_METHOD_EXTENDED_LUN = 3,
+};
+
+/*
+ * srpt_unpack_lun() - Convert from network LUN to linear LUN.
+ *
+ * Convert an 2-byte, 4-byte, 6-byte or 8-byte LUN structure in network byte
+ * order (big endian) to a linear LUN. Supports three LUN addressing methods:
+ * peripheral, flat and logical unit. See also SAM-2, section 4.9.4 (page 40).
+ */
+static uint64_t srpt_unpack_lun(const uint8_t *lun, int len)
+{
+ uint64_t res = NO_SUCH_LUN;
+ int addressing_method;
+
+ if (unlikely(len < 2)) {
+ printk(KERN_ERR "Illegal LUN length %d, expected 2 bytes or "
+ "more", len);
+ goto out;
+ }
+
+ switch (len) {
+ case 8:
+ if ((*((__be64 *)lun) &
+ __constant_cpu_to_be64(0x0000FFFFFFFFFFFFLL)) != 0)
+ goto out_err;
+ break;
+ case 4:
+ if (*((__be16 *)&lun[2]) != 0)
+ goto out_err;
+ break;
+ case 6:
+ if (*((__be32 *)&lun[2]) != 0)
+ goto out_err;
+ break;
+ case 2:
+ break;
+ default:
+ goto out_err;
+ }
+
+ addressing_method = (*lun) >> 6; /* highest two bits of byte 0 */
+ switch (addressing_method) {
+ case SCSI_LUN_ADDR_METHOD_PERIPHERAL:
+ case SCSI_LUN_ADDR_METHOD_FLAT:
+ case SCSI_LUN_ADDR_METHOD_LUN:
+ res = *(lun + 1) | (((*lun) & 0x3f) << 8);
+ break;
+
+ case SCSI_LUN_ADDR_METHOD_EXTENDED_LUN:
+ default:
+ printk(KERN_ERR "Unimplemented LUN addressing method %u",
+ addressing_method);
+ break;
+ }
+
+out:
+ return res;
+
+out_err:
+ printk(KERN_ERR "Support for multi-level LUNs has not yet been"
+ " implemented");
+ goto out;
+}
+
+static int srpt_check_stop_free(struct se_cmd *cmd)
+{
+ struct srpt_send_ioctx *ioctx;
+
+ ioctx = container_of(cmd, struct srpt_send_ioctx, cmd);
+ return kref_put(&ioctx->kref, srpt_put_send_ioctx_kref);
+}
+
+/**
+ * srpt_handle_cmd() - Process SRP_CMD.
+ */
+static int srpt_handle_cmd(struct srpt_rdma_ch *ch,
+ struct srpt_recv_ioctx *recv_ioctx,
+ struct srpt_send_ioctx *send_ioctx)
+{
+ struct se_cmd *cmd;
+ struct srp_cmd *srp_cmd;
+ uint64_t unpacked_lun;
+ u64 data_len;
+ enum dma_data_direction dir;
+ int ret;
+
+ BUG_ON(!send_ioctx);
+
+ srp_cmd = recv_ioctx->ioctx.buf;
+ kref_get(&send_ioctx->kref);
+ cmd = &send_ioctx->cmd;
+ send_ioctx->tag = srp_cmd->tag;
+
+ switch (srp_cmd->task_attr) {
+ case SRP_CMD_SIMPLE_Q:
+ cmd->sam_task_attr = MSG_SIMPLE_TAG;
+ break;
+ case SRP_CMD_ORDERED_Q:
+ default:
+ cmd->sam_task_attr = MSG_ORDERED_TAG;
+ break;
+ case SRP_CMD_HEAD_OF_Q:
+ cmd->sam_task_attr = MSG_HEAD_TAG;
+ break;
+ case SRP_CMD_ACA:
+ cmd->sam_task_attr = MSG_ACA_TAG;
+ break;
+ }
+
+ ret = srpt_get_desc_tbl(send_ioctx, srp_cmd, &dir, &data_len);
+ if (ret) {
+ printk(KERN_ERR "0x%llx: parsing SRP descriptor table failed.\n",
+ srp_cmd->tag);
+ cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+ cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
+ goto send_sense;
+ }
+
+ cmd->data_length = data_len;
+ cmd->data_direction = dir;
+ unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_cmd->lun,
+ sizeof(srp_cmd->lun));
+ if (transport_lookup_cmd_lun(cmd, unpacked_lun) < 0)
+ goto send_sense;
+ ret = transport_generic_allocate_tasks(cmd, srp_cmd->cdb);
+ if (cmd->se_cmd_flags & SCF_SCSI_RESERVATION_CONFLICT)
+ srpt_queue_status(cmd);
+ else if (cmd->se_cmd_flags & SCF_SCSI_CDB_EXCEPTION)
+ goto send_sense;
+ else
+ WARN_ON_ONCE(ret);
+
+ transport_handle_cdb_direct(cmd);
+ return 0;
+
+send_sense:
+ transport_send_check_condition_and_sense(cmd, cmd->scsi_sense_reason,
+ 0);
+ return -1;
+}
+
+/**
+ * srpt_rx_mgmt_fn_tag() - Process a task management function by tag.
+ * @ch: RDMA channel of the task management request.
+ * @fn: Task management function to perform.
+ * @req_tag: Tag of the SRP task management request.
+ * @mgmt_ioctx: I/O context of the task management request.
+ *
+ * Returns zero if the target core will process the task management
+ * request asynchronously.
+ *
+ * Note: It is assumed that the initiator serializes tag-based task management
+ * requests.
+ */
+static int srpt_rx_mgmt_fn_tag(struct srpt_send_ioctx *ioctx, u64 tag)
+{
+ struct srpt_device *sdev;
+ struct srpt_rdma_ch *ch;
+ struct srpt_send_ioctx *target;
+ int ret, i;
+
+ ret = -EINVAL;
+ ch = ioctx->ch;
+ BUG_ON(!ch);
+ BUG_ON(!ch->sport);
+ sdev = ch->sport->sdev;
+ BUG_ON(!sdev);
+ spin_lock_irq(&sdev->spinlock);
+ for (i = 0; i < ch->rq_size; ++i) {
+ target = ch->ioctx_ring[i];
+ if (target->cmd.se_lun == ioctx->cmd.se_lun &&
+ target->tag == tag &&
+ srpt_get_cmd_state(target) != SRPT_STATE_DONE) {
+ ret = 0;
+ /* now let the target core abort &target->cmd; */
+ break;
+ }
+ }
+ spin_unlock_irq(&sdev->spinlock);
+ return ret;
+}
+
+static int srp_tmr_to_tcm(int fn)
+{
+ switch (fn) {
+ case SRP_TSK_ABORT_TASK:
+ return TMR_ABORT_TASK;
+ case SRP_TSK_ABORT_TASK_SET:
+ return TMR_ABORT_TASK_SET;
+ case SRP_TSK_CLEAR_TASK_SET:
+ return TMR_CLEAR_TASK_SET;
+ case SRP_TSK_LUN_RESET:
+ return TMR_LUN_RESET;
+ case SRP_TSK_CLEAR_ACA:
+ return TMR_CLEAR_ACA;
+ default:
+ return -1;
+ }
+}
+
+/**
+ * srpt_handle_tsk_mgmt() - Process an SRP_TSK_MGMT information unit.
+ *
+ * Returns 0 if and only if the request will be processed by the target core.
+ *
+ * For more information about SRP_TSK_MGMT information units, see also section
+ * 6.7 in the SRP r16a document.
+ */
+static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch,
+ struct srpt_recv_ioctx *recv_ioctx,
+ struct srpt_send_ioctx *send_ioctx)
+{
+ struct srp_tsk_mgmt *srp_tsk;
+ struct se_cmd *cmd;
+ uint64_t unpacked_lun;
+ int tcm_tmr;
+ int res;
+
+ BUG_ON(!send_ioctx);
+
+ srp_tsk = recv_ioctx->ioctx.buf;
+ cmd = &send_ioctx->cmd;
+
+ pr_debug("recv tsk_mgmt fn %d for task_tag %lld and cmd tag %lld"
+ " cm_id %p sess %p\n", srp_tsk->tsk_mgmt_func,
+ srp_tsk->task_tag, srp_tsk->tag, ch->cm_id, ch->sess);
+
+ srpt_set_cmd_state(send_ioctx, SRPT_STATE_MGMT);
+ send_ioctx->tag = srp_tsk->tag;
+ tcm_tmr = srp_tmr_to_tcm(srp_tsk->tsk_mgmt_func);
+ if (tcm_tmr < 0) {
+ send_ioctx->cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+ send_ioctx->cmd.se_tmr_req->response =
+ TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED;
+ goto process_tmr;
+ }
+ cmd->se_tmr_req = core_tmr_alloc_req(cmd, NULL, tcm_tmr, GFP_KERNEL);
+ if (!cmd->se_tmr_req) {
+ send_ioctx->cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+ send_ioctx->cmd.se_tmr_req->response = TMR_FUNCTION_REJECTED;
+ goto process_tmr;
+ }
+
+ unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_tsk->lun,
+ sizeof(srp_tsk->lun));
+ res = transport_lookup_tmr_lun(&send_ioctx->cmd, unpacked_lun);
+ if (res) {
+ pr_debug("rejecting TMR for LUN %lld\n", unpacked_lun);
+ send_ioctx->cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+ send_ioctx->cmd.se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST;
+ goto process_tmr;
+ }
+
+ if (srp_tsk->tsk_mgmt_func == SRP_TSK_ABORT_TASK)
+ srpt_rx_mgmt_fn_tag(send_ioctx, srp_tsk->task_tag);
+
+process_tmr:
+ kref_get(&send_ioctx->kref);
+ if (!(send_ioctx->cmd.se_cmd_flags & SCF_SCSI_CDB_EXCEPTION))
+ transport_generic_handle_tmr(&send_ioctx->cmd);
+ else
+ transport_send_check_condition_and_sense(cmd,
+ cmd->scsi_sense_reason, 0);
+
+}
+
+/**
+ * srpt_handle_new_iu() - Process a newly received information unit.
+ * @ch: RDMA channel through which the information unit has been received.
+ * @ioctx: SRPT I/O context associated with the information unit.
+ */
+static void srpt_handle_new_iu(struct srpt_rdma_ch *ch,
+ struct srpt_recv_ioctx *recv_ioctx,
+ struct srpt_send_ioctx *send_ioctx)
+{
+ struct srp_cmd *srp_cmd;
+ enum rdma_ch_state ch_state;
+
+ BUG_ON(!ch);
+ BUG_ON(!recv_ioctx);
+
+ ib_dma_sync_single_for_cpu(ch->sport->sdev->device,
+ recv_ioctx->ioctx.dma, srp_max_req_size,
+ DMA_FROM_DEVICE);
+
+ ch_state = srpt_get_ch_state(ch);
+ if (unlikely(ch_state == CH_CONNECTING)) {
+ list_add_tail(&recv_ioctx->wait_list, &ch->cmd_wait_list);
+ goto out;
+ }
+
+ if (unlikely(ch_state != CH_LIVE))
+ goto out;
+
+ srp_cmd = recv_ioctx->ioctx.buf;
+ if (srp_cmd->opcode == SRP_CMD || srp_cmd->opcode == SRP_TSK_MGMT) {
+ if (!send_ioctx)
+ send_ioctx = srpt_get_send_ioctx(ch);
+ if (unlikely(!send_ioctx)) {
+ list_add_tail(&recv_ioctx->wait_list,
+ &ch->cmd_wait_list);
+ goto out;
+ }
+ }
+
+ transport_init_se_cmd(&send_ioctx->cmd, &srpt_target->tf_ops, ch->sess,
+ 0, DMA_NONE, MSG_SIMPLE_TAG,
+ send_ioctx->sense_data);
+
+ switch (srp_cmd->opcode) {
+ case SRP_CMD:
+ srpt_handle_cmd(ch, recv_ioctx, send_ioctx);
+ break;
+ case SRP_TSK_MGMT:
+ srpt_handle_tsk_mgmt(ch, recv_ioctx, send_ioctx);
+ break;
+ case SRP_I_LOGOUT:
+ printk(KERN_ERR "Not yet implemented: SRP_I_LOGOUT\n");
+ break;
+ case SRP_CRED_RSP:
+ pr_debug("received SRP_CRED_RSP\n");
+ break;
+ case SRP_AER_RSP:
+ pr_debug("received SRP_AER_RSP\n");
+ break;
+ case SRP_RSP:
+ printk(KERN_ERR "Received SRP_RSP\n");
+ break;
+ default:
+ printk(KERN_ERR "received IU with unknown opcode 0x%x\n",
+ srp_cmd->opcode);
+ break;
+ }
+
+ srpt_post_recv(ch->sport->sdev, recv_ioctx);
+out:
+ return;
+}
+
+static void srpt_process_rcv_completion(struct ib_cq *cq,
+ struct srpt_rdma_ch *ch,
+ struct ib_wc *wc)
+{
+ struct srpt_device *sdev = ch->sport->sdev;
+ struct srpt_recv_ioctx *ioctx;
+ u32 index;
+
+ index = idx_from_wr_id(wc->wr_id);
+ if (wc->status == IB_WC_SUCCESS) {
+ int req_lim;
+
+ req_lim = atomic_dec_return(&ch->req_lim);
+ if (unlikely(req_lim < 0))
+ printk(KERN_ERR "req_lim = %d < 0\n", req_lim);
+ ioctx = sdev->ioctx_ring[index];
+ srpt_handle_new_iu(ch, ioctx, NULL);
+ } else {
+ printk(KERN_INFO "receiving failed for idx %u with status %d\n",
+ index, wc->status);
+ }
+}
+
+/**
+ * srpt_process_send_completion() - Process an IB send completion.
+ *
+ * Note: Although this has not yet been observed during tests, at least in
+ * theory it is possible that the srpt_get_send_ioctx() call invoked by
+ * srpt_handle_new_iu() fails. This is possible because the req_lim_delta
+ * value in each response is set to one, and it is possible that this response
+ * makes the initiator send a new request before the send completion for that
+ * response has been processed. This could e.g. happen if the call to
+ * srpt_put_send_iotcx() is delayed because of a higher priority interrupt or
+ * if IB retransmission causes generation of the send completion to be
+ * delayed. Incoming information units for which srpt_get_send_ioctx() fails
+ * are queued on cmd_wait_list. The code below processes these delayed
+ * requests one at a time.
+ */
+static void srpt_process_send_completion(struct ib_cq *cq,
+ struct srpt_rdma_ch *ch,
+ struct ib_wc *wc)
+{
+ struct srpt_send_ioctx *send_ioctx;
+ uint32_t index;
+ enum srpt_opcode opcode;
+
+ index = idx_from_wr_id(wc->wr_id);
+ opcode = opcode_from_wr_id(wc->wr_id);
+ send_ioctx = ch->ioctx_ring[index];
+ if (wc->status == IB_WC_SUCCESS) {
+ if (opcode == SRPT_SEND)
+ srpt_handle_send_comp(ch, send_ioctx);
+ else {
+ WARN_ON(opcode != SRPT_RDMA_ABORT &&
+ wc->opcode != IB_WC_RDMA_READ);
+ srpt_handle_rdma_comp(ch, send_ioctx, opcode);
+ }
+ } else {
+ if (opcode == SRPT_SEND) {
+ printk(KERN_INFO "sending response for idx %u failed"
+ " with status %d\n", index, wc->status);
+ srpt_handle_send_err_comp(ch, wc->wr_id);
+ } else if (opcode != SRPT_RDMA_MID) {
+ printk(KERN_INFO "RDMA t %d for idx %u failed with"
+ " status %d", opcode, index, wc->status);
+ srpt_handle_rdma_err_comp(ch, send_ioctx, opcode);
+ }
+ }
+
+ while (unlikely(opcode == SRPT_SEND
+ && !list_empty(&ch->cmd_wait_list)
+ && srpt_get_ch_state(ch) == CH_LIVE
+ && (send_ioctx = srpt_get_send_ioctx(ch)) != NULL)) {
+ struct srpt_recv_ioctx *recv_ioctx;
+
+ recv_ioctx = list_first_entry(&ch->cmd_wait_list,
+ struct srpt_recv_ioctx,
+ wait_list);
+ list_del(&recv_ioctx->wait_list);
+ srpt_handle_new_iu(ch, recv_ioctx, send_ioctx);
+ }
+}
+
+static void srpt_process_completion(struct ib_cq *cq, struct srpt_rdma_ch *ch)
+{
+ struct ib_wc *const wc = ch->wc;
+ int i, n;
+
+ WARN_ON(cq != ch->cq);
+
+ ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);
+ while ((n = ib_poll_cq(cq, ARRAY_SIZE(ch->wc), wc)) > 0) {
+ for (i = 0; i < n; i++) {
+ if (opcode_from_wr_id(wc[i].wr_id) == SRPT_RECV)
+ srpt_process_rcv_completion(cq, ch, &wc[i]);
+ else
+ srpt_process_send_completion(cq, ch, &wc[i]);
+ }
+ }
+}
+
+/**
+ * srpt_completion() - IB completion queue callback function.
+ *
+ * Notes:
+ * - It is guaranteed that a completion handler will never be invoked
+ * concurrently on two different CPUs for the same completion queue. See also
+ * Documentation/infiniband/core_locking.txt and the implementation of
+ * handle_edge_irq() in kernel/irq/chip.c.
+ * - When threaded IRQs are enabled, completion handlers are invoked in thread
+ * context instead of interrupt context.
+ */
+static void srpt_completion(struct ib_cq *cq, void *ctx)
+{
+ struct srpt_rdma_ch *ch = ctx;
+
+ wake_up_interruptible(&ch->wait_queue);
+}
+
+static int srpt_compl_thread(void *arg)
+{
+ struct srpt_rdma_ch *ch;
+
+ /* Hibernation / freezing of the SRPT kernel thread is not supported. */
+ current->flags |= PF_NOFREEZE;
+
+ ch = arg;
+ BUG_ON(!ch);
+ printk(KERN_INFO "Session %s: kernel thread %s (PID %d) started\n",
+ ch->sess_name, ch->thread->comm, current->pid);
+ while (!kthread_should_stop()) {
+ wait_event_interruptible(ch->wait_queue,
+ (srpt_process_completion(ch->cq, ch),
+ kthread_should_stop()));
+ }
+ printk(KERN_INFO "Session %s: kernel thread %s (PID %d) stopped\n",
+ ch->sess_name, ch->thread->comm, current->pid);
+ return 0;
+}
+
+/**
+ * srpt_create_ch_ib() - Create receive and send completion queues.
+ */
+static int srpt_create_ch_ib(struct srpt_rdma_ch *ch)
+{
+ struct ib_qp_init_attr *qp_init;
+ struct srpt_port *sport = ch->sport;
+ struct srpt_device *sdev = sport->sdev;
+ u32 srp_sq_size = sport->port_attrib.srp_sq_size;
+ int ret;
+
+ WARN_ON(ch->rq_size < 1);
+
+ ret = -ENOMEM;
+ qp_init = kzalloc(sizeof *qp_init, GFP_KERNEL);
+ if (!qp_init)
+ goto out;
+
+ ch->cq = ib_create_cq(sdev->device, srpt_completion, NULL, ch,
+ ch->rq_size + srp_sq_size, 0);
+ if (IS_ERR(ch->cq)) {
+ ret = PTR_ERR(ch->cq);
+ printk(KERN_ERR "failed to create CQ cqe= %d ret= %d\n",
+ ch->rq_size + srp_sq_size, ret);
+ goto out;
+ }
+
+ qp_init->qp_context = (void *)ch;
+ qp_init->event_handler
+ = (void(*)(struct ib_event *, void*))srpt_qp_event;
+ qp_init->send_cq = ch->cq;
+ qp_init->recv_cq = ch->cq;
+ qp_init->srq = sdev->srq;
+ qp_init->sq_sig_type = IB_SIGNAL_REQ_WR;
+ qp_init->qp_type = IB_QPT_RC;
+ qp_init->cap.max_send_wr = srp_sq_size;
+ qp_init->cap.max_send_sge = SRPT_DEF_SG_PER_WQE;
+
+ ch->qp = ib_create_qp(sdev->pd, qp_init);
+ if (IS_ERR(ch->qp)) {
+ ret = PTR_ERR(ch->qp);
+ printk(KERN_ERR "failed to create_qp ret= %d\n", ret);
+ goto err_destroy_cq;
+ }
+
+ atomic_set(&ch->sq_wr_avail, qp_init->cap.max_send_wr);
+
+ pr_debug("%s: max_cqe= %d max_sge= %d sq_size = %d cm_id= %p\n",
+ __func__, ch->cq->cqe, qp_init->cap.max_send_sge,
+ qp_init->cap.max_send_wr, ch->cm_id);
+
+ ret = srpt_init_ch_qp(ch, ch->qp);
+ if (ret)
+ goto err_destroy_qp;
+
+ init_waitqueue_head(&ch->wait_queue);
+
+ pr_debug("creating thread for session %s\n", ch->sess_name);
+
+ ch->thread = kthread_run(srpt_compl_thread, ch, "ib_srpt_compl");
+ if (IS_ERR(ch->thread)) {
+ printk(KERN_ERR "failed to create kernel thread %ld\n",
+ PTR_ERR(ch->thread));
+ ch->thread = NULL;
+ goto err_destroy_qp;
+ }
+
+out:
+ kfree(qp_init);
+ return ret;
+
+err_destroy_qp:
+ ib_destroy_qp(ch->qp);
+err_destroy_cq:
+ ib_destroy_cq(ch->cq);
+ goto out;
+}
+
+static void srpt_destroy_ch_ib(struct srpt_rdma_ch *ch)
+{
+ if (ch->thread)
+ kthread_stop(ch->thread);
+
+ ib_destroy_qp(ch->qp);
+ ib_destroy_cq(ch->cq);
+}
+
+/**
+ * __srpt_close_ch() - Close an RDMA channel by setting the QP error state.
+ *
+ * Reset the QP and make sure all resources associated with the channel will
+ * be deallocated at an appropriate time.
+ *
+ * Note: The caller must hold ch->sport->sdev->spinlock.
+ */
+static void __srpt_close_ch(struct srpt_rdma_ch *ch)
+{
+ struct srpt_device *sdev;
+ enum rdma_ch_state prev_state;
+ unsigned long flags;
+
+ sdev = ch->sport->sdev;
+
+ spin_lock_irqsave(&ch->spinlock, flags);
+ prev_state = ch->state;
+ switch (prev_state) {
+ case CH_CONNECTING:
+ case CH_LIVE:
+ ch->state = CH_DISCONNECTING;
+ break;
+ default:
+ break;
+ }
+ spin_unlock_irqrestore(&ch->spinlock, flags);
+
+ switch (prev_state) {
+ case CH_CONNECTING:
+ ib_send_cm_rej(ch->cm_id, IB_CM_REJ_NO_RESOURCES, NULL, 0,
+ NULL, 0);
+ /* fall through */
+ case CH_LIVE:
+ if (ib_send_cm_dreq(ch->cm_id, NULL, 0) < 0)
+ printk(KERN_ERR "sending CM DREQ failed.\n");
+ break;
+ case CH_DISCONNECTING:
+ break;
+ case CH_DRAINING:
+ case CH_RELEASING:
+ break;
+ }
+}
+
+/**
+ * srpt_close_ch() - Close an RDMA channel.
+ */
+static void srpt_close_ch(struct srpt_rdma_ch *ch)
+{
+ struct srpt_device *sdev;
+
+ sdev = ch->sport->sdev;
+ spin_lock_irq(&sdev->spinlock);
+ __srpt_close_ch(ch);
+ spin_unlock_irq(&sdev->spinlock);
+}
+
+/**
+ * srpt_drain_channel() - Drain a channel by resetting the IB queue pair.
+ * @cm_id: Pointer to the CM ID of the channel to be drained.
+ *
+ * Note: Must be called from inside srpt_cm_handler to avoid a race between
+ * accessing sdev->spinlock and the call to kfree(sdev) in srpt_remove_one()
+ * (the caller of srpt_cm_handler holds the cm_id spinlock; srpt_remove_one()
+ * waits until all target sessions for the associated IB device have been
+ * unregistered and target session registration involves a call to
+ * ib_destroy_cm_id(), which locks the cm_id spinlock and hence waits until
+ * this function has finished).
+ */
+static void srpt_drain_channel(struct ib_cm_id *cm_id)
+{
+ struct srpt_device *sdev;
+ struct srpt_rdma_ch *ch;
+ int ret;
+ bool do_reset = false;
+
+ WARN_ON_ONCE(irqs_disabled());
+
+ sdev = cm_id->context;
+ BUG_ON(!sdev);
+ spin_lock_irq(&sdev->spinlock);
+ list_for_each_entry(ch, &sdev->rch_list, list) {
+ if (ch->cm_id == cm_id) {
+ do_reset = srpt_test_and_set_ch_state(ch,
+ CH_CONNECTING, CH_DRAINING) ||
+ srpt_test_and_set_ch_state(ch,
+ CH_LIVE, CH_DRAINING) ||
+ srpt_test_and_set_ch_state(ch,
+ CH_DISCONNECTING, CH_DRAINING);
+ break;
+ }
+ }
+ spin_unlock_irq(&sdev->spinlock);
+
+ if (do_reset) {
+ ret = srpt_ch_qp_err(ch);
+ if (ret < 0)
+ printk(KERN_ERR "Setting queue pair in error state"
+ " failed: %d\n", ret);
+ }
+}
+
+/**
+ * srpt_find_channel() - Look up an RDMA channel.
+ * @cm_id: Pointer to the CM ID of the channel to be looked up.
+ *
+ * Return NULL if no matching RDMA channel has been found.
+ */
+static struct srpt_rdma_ch *srpt_find_channel(struct srpt_device *sdev,
+ struct ib_cm_id *cm_id)
+{
+ struct srpt_rdma_ch *ch;
+ bool found;
+
+ WARN_ON_ONCE(irqs_disabled());
+ BUG_ON(!sdev);
+
+ found = false;
+ spin_lock_irq(&sdev->spinlock);
+ list_for_each_entry(ch, &sdev->rch_list, list) {
+ if (ch->cm_id == cm_id) {
+ found = true;
+ break;
+ }
+ }
+ spin_unlock_irq(&sdev->spinlock);
+
+ return found ? ch : NULL;
+}
+
+/**
+ * srpt_release_channel() - Release channel resources.
+ *
+ * Schedules the actual release because:
+ * - Calling the ib_destroy_cm_id() call from inside an IB CM callback would
+ * trigger a deadlock.
+ * - It is not safe to call TCM transport_* functions from interrupt context.
+ */
+static void srpt_release_channel(struct srpt_rdma_ch *ch)
+{
+ schedule_work(&ch->release_work);
+}
+
+static void srpt_release_channel_work(struct work_struct *w)
+{
+ struct srpt_rdma_ch *ch;
+ struct srpt_device *sdev;
+
+ ch = container_of(w, struct srpt_rdma_ch, release_work);
+ pr_debug("ch = %p; ch->sess = %p; release_done = %p\n", ch, ch->sess,
+ ch->release_done);
+
+ sdev = ch->sport->sdev;
+ BUG_ON(!sdev);
+
+ transport_deregister_session_configfs(ch->sess);
+ transport_deregister_session(ch->sess);
+ ch->sess = NULL;
+
+ srpt_destroy_ch_ib(ch);
+
+ srpt_free_ioctx_ring((struct srpt_ioctx **)ch->ioctx_ring,
+ ch->sport->sdev, ch->rq_size,
+ ch->rsp_size, DMA_TO_DEVICE);
+
+ spin_lock_irq(&sdev->spinlock);
+ list_del(&ch->list);
+ spin_unlock_irq(&sdev->spinlock);
+
+ ib_destroy_cm_id(ch->cm_id);
+
+ if (ch->release_done)
+ complete(ch->release_done);
+
+ wake_up(&sdev->ch_releaseQ);
+
+ kfree(ch);
+}
+
+static struct srpt_node_acl *__srpt_lookup_acl(struct srpt_port *sport,
+ u8 i_port_id[16])
+{
+ struct srpt_node_acl *nacl;
+
+ list_for_each_entry(nacl, &sport->port_acl_list, list)
+ if (memcmp(nacl->i_port_id, i_port_id,
+ sizeof(nacl->i_port_id)) == 0)
+ return nacl;
+
+ return NULL;
+}
+
+static struct srpt_node_acl *srpt_lookup_acl(struct srpt_port *sport,
+ u8 i_port_id[16])
+{
+ struct srpt_node_acl *nacl;
+
+ spin_lock_irq(&sport->port_acl_lock);
+ nacl = __srpt_lookup_acl(sport, i_port_id);
+ spin_unlock_irq(&sport->port_acl_lock);
+
+ return nacl;
+}
+
+/**
+ * srpt_cm_req_recv() - Process the event IB_CM_REQ_RECEIVED.
+ *
+ * Ownership of the cm_id is transferred to the target session if this
+ * functions returns zero. Otherwise the caller remains the owner of cm_id.
+ */
+static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
+ struct ib_cm_req_event_param *param,
+ void *private_data)
+{
+ struct srpt_device *sdev = cm_id->context;
+ struct srpt_port *sport = &sdev->port[param->port - 1];
+ struct srp_login_req *req;
+ struct srp_login_rsp *rsp;
+ struct srp_login_rej *rej;
+ struct ib_cm_rep_param *rep_param;
+ struct srpt_rdma_ch *ch, *tmp_ch;
+ struct srpt_node_acl *nacl;
+ u32 it_iu_len;
+ int i;
+ int ret = 0;
+
+ WARN_ON_ONCE(irqs_disabled());
+
+ if (WARN_ON(!sdev || !private_data))
+ return -EINVAL;
+
+ req = (struct srp_login_req *)private_data;
+
+ it_iu_len = be32_to_cpu(req->req_it_iu_len);
+
+ printk(KERN_INFO "Received SRP_LOGIN_REQ with i_port_id 0x%llx:0x%llx,"
+ " t_port_id 0x%llx:0x%llx and it_iu_len %d on port %d"
+ " (guid=0x%llx:0x%llx)\n",
+ be64_to_cpu(*(__be64 *)&req->initiator_port_id[0]),
+ be64_to_cpu(*(__be64 *)&req->initiator_port_id[8]),
+ be64_to_cpu(*(__be64 *)&req->target_port_id[0]),
+ be64_to_cpu(*(__be64 *)&req->target_port_id[8]),
+ it_iu_len,
+ param->port,
+ be64_to_cpu(*(__be64 *)&sdev->port[param->port - 1].gid.raw[0]),
+ be64_to_cpu(*(__be64 *)&sdev->port[param->port - 1].gid.raw[8]));
+
+ rsp = kzalloc(sizeof *rsp, GFP_KERNEL);
+ rej = kzalloc(sizeof *rej, GFP_KERNEL);
+ rep_param = kzalloc(sizeof *rep_param, GFP_KERNEL);
+
+ if (!rsp || !rej || !rep_param) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ if (it_iu_len > srp_max_req_size || it_iu_len < 64) {
+ rej->reason = __constant_cpu_to_be32(
+ SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE);
+ ret = -EINVAL;
+ printk(KERN_ERR "rejected SRP_LOGIN_REQ because its"
+ " length (%d bytes) is out of range (%d .. %d)\n",
+ it_iu_len, 64, srp_max_req_size);
+ goto reject;
+ }
+
+ if (!sport->enabled) {
+ rej->reason = __constant_cpu_to_be32(
+ SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
+ ret = -EINVAL;
+ printk(KERN_ERR "rejected SRP_LOGIN_REQ because the target port"
+ " has not yet been enabled\n");
+ goto reject;
+ }
+
+ if ((req->req_flags & SRP_MTCH_ACTION) == SRP_MULTICHAN_SINGLE) {
+ rsp->rsp_flags = SRP_LOGIN_RSP_MULTICHAN_NO_CHAN;
+
+ spin_lock_irq(&sdev->spinlock);
+
+ list_for_each_entry_safe(ch, tmp_ch, &sdev->rch_list, list) {
+ if (!memcmp(ch->i_port_id, req->initiator_port_id, 16)
+ && !memcmp(ch->t_port_id, req->target_port_id, 16)
+ && param->port == ch->sport->port
+ && param->listen_id == ch->sport->sdev->cm_id
+ && ch->cm_id) {
+ enum rdma_ch_state ch_state;
+
+ ch_state = srpt_get_ch_state(ch);
+ if (ch_state != CH_CONNECTING
+ && ch_state != CH_LIVE)
+ continue;
+
+ /* found an existing channel */
+ pr_debug("Found existing channel %s"
+ " cm_id= %p state= %d\n",
+ ch->sess_name, ch->cm_id, ch_state);
+
+ __srpt_close_ch(ch);
+
+ rsp->rsp_flags =
+ SRP_LOGIN_RSP_MULTICHAN_TERMINATED;
+ }
+ }
+
+ spin_unlock_irq(&sdev->spinlock);
+
+ } else
+ rsp->rsp_flags = SRP_LOGIN_RSP_MULTICHAN_MAINTAINED;
+
+ if (*(__be64 *)req->target_port_id != cpu_to_be64(srpt_service_guid)
+ || *(__be64 *)(req->target_port_id + 8) !=
+ cpu_to_be64(srpt_service_guid)) {
+ rej->reason = __constant_cpu_to_be32(
+ SRP_LOGIN_REJ_UNABLE_ASSOCIATE_CHANNEL);
+ ret = -ENOMEM;
+ printk(KERN_ERR "rejected SRP_LOGIN_REQ because it"
+ " has an invalid target port identifier.\n");
+ goto reject;
+ }
+
+ ch = kzalloc(sizeof *ch, GFP_KERNEL);
+ if (!ch) {
+ rej->reason = __constant_cpu_to_be32(
+ SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
+ printk(KERN_ERR "rejected SRP_LOGIN_REQ because no memory.\n");
+ ret = -ENOMEM;
+ goto reject;
+ }
+
+ INIT_WORK(&ch->release_work, srpt_release_channel_work);
+ memcpy(ch->i_port_id, req->initiator_port_id, 16);
+ memcpy(ch->t_port_id, req->target_port_id, 16);
+ ch->sport = &sdev->port[param->port - 1];
+ ch->cm_id = cm_id;
+ /*
+ * Avoid QUEUE_FULL conditions by limiting the number of buffers used
+ * for the SRP protocol to the command queue size.
+ */
+ ch->rq_size = SRPT_RQ_SIZE;
+ spin_lock_init(&ch->spinlock);
+ ch->state = CH_CONNECTING;
+ INIT_LIST_HEAD(&ch->cmd_wait_list);
+ ch->rsp_size = ch->sport->port_attrib.srp_max_rsp_size;
+
+ ch->ioctx_ring = (struct srpt_send_ioctx **)
+ srpt_alloc_ioctx_ring(ch->sport->sdev, ch->rq_size,
+ sizeof(*ch->ioctx_ring[0]),
+ ch->rsp_size, DMA_TO_DEVICE);
+ if (!ch->ioctx_ring)
+ goto free_ch;
+
+ INIT_LIST_HEAD(&ch->free_list);
+ for (i = 0; i < ch->rq_size; i++) {
+ ch->ioctx_ring[i]->ch = ch;
+ list_add_tail(&ch->ioctx_ring[i]->free_list, &ch->free_list);
+ }
+
+ ret = srpt_create_ch_ib(ch);
+ if (ret) {
+ rej->reason = __constant_cpu_to_be32(
+ SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
+ printk(KERN_ERR "rejected SRP_LOGIN_REQ because creating"
+ " a new RDMA channel failed.\n");
+ goto free_ring;
+ }
+
+ ret = srpt_ch_qp_rtr(ch, ch->qp);
+ if (ret) {
+ rej->reason = __constant_cpu_to_be32(
+ SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
+ printk(KERN_ERR "rejected SRP_LOGIN_REQ because enabling"
+ " RTR failed (error code = %d)\n", ret);
+ goto destroy_ib;
+ }
+ /*
+ * Use the initator port identifier as the session name.
+ */
+ snprintf(ch->sess_name, sizeof(ch->sess_name), "0x%016llx%016llx",
+ be64_to_cpu(*(__be64 *)ch->i_port_id),
+ be64_to_cpu(*(__be64 *)(ch->i_port_id + 8)));
+
+ pr_debug("registering session %s\n", ch->sess_name);
+
+ nacl = srpt_lookup_acl(sport, ch->i_port_id);
+ if (!nacl) {
+ printk(KERN_INFO "Rejected login because no ACL has been"
+ " configured yet for initiator %s.\n", ch->sess_name);
+ rej->reason = __constant_cpu_to_be32(
+ SRP_LOGIN_REJ_CHANNEL_LIMIT_REACHED);
+ goto destroy_ib;
+ }
+
+ ch->sess = transport_init_session();
+ if (!ch->sess) {
+ rej->reason = __constant_cpu_to_be32(
+ SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
+ pr_debug("Failed to create session\n");
+ goto deregister_session;
+ }
+ ch->sess->se_node_acl = &nacl->nacl;
+ transport_register_session(&sport->port_tpg_1, &nacl->nacl, ch->sess, ch);
+
+ pr_debug("Establish connection sess=%p name=%s cm_id=%p\n", ch->sess,
+ ch->sess_name, ch->cm_id);
+
+ /* create srp_login_response */
+ rsp->opcode = SRP_LOGIN_RSP;
+ rsp->tag = req->tag;
+ rsp->max_it_iu_len = req->req_it_iu_len;
+ rsp->max_ti_iu_len = req->req_it_iu_len;
+ ch->max_ti_iu_len = it_iu_len;
+ rsp->buf_fmt = __constant_cpu_to_be16(SRP_BUF_FORMAT_DIRECT
+ | SRP_BUF_FORMAT_INDIRECT);
+ rsp->req_lim_delta = cpu_to_be32(ch->rq_size);
+ atomic_set(&ch->req_lim, ch->rq_size);
+ atomic_set(&ch->req_lim_delta, 0);
+
+ /* create cm reply */
+ rep_param->qp_num = ch->qp->qp_num;
+ rep_param->private_data = (void *)rsp;
+ rep_param->private_data_len = sizeof *rsp;
+ rep_param->rnr_retry_count = 7;
+ rep_param->flow_control = 1;
+ rep_param->failover_accepted = 0;
+ rep_param->srq = 1;
+ rep_param->responder_resources = 4;
+ rep_param->initiator_depth = 4;
+
+ ret = ib_send_cm_rep(cm_id, rep_param);
+ if (ret) {
+ printk(KERN_ERR "sending SRP_LOGIN_REQ response failed"
+ " (error code = %d)\n", ret);
+ goto release_channel;
+ }
+
+ spin_lock_irq(&sdev->spinlock);
+ list_add_tail(&ch->list, &sdev->rch_list);
+ spin_unlock_irq(&sdev->spinlock);
+
+ goto out;
+
+release_channel:
+ srpt_set_ch_state(ch, CH_RELEASING);
+ transport_deregister_session_configfs(ch->sess);
+
+deregister_session:
+ transport_deregister_session(ch->sess);
+ ch->sess = NULL;
+
+destroy_ib:
+ srpt_destroy_ch_ib(ch);
+
+free_ring:
+ srpt_free_ioctx_ring((struct srpt_ioctx **)ch->ioctx_ring,
+ ch->sport->sdev, ch->rq_size,
+ ch->rsp_size, DMA_TO_DEVICE);
+free_ch:
+ kfree(ch);
+
+reject:
+ rej->opcode = SRP_LOGIN_REJ;
+ rej->tag = req->tag;
+ rej->buf_fmt = __constant_cpu_to_be16(SRP_BUF_FORMAT_DIRECT
+ | SRP_BUF_FORMAT_INDIRECT);
+
+ ib_send_cm_rej(cm_id, IB_CM_REJ_CONSUMER_DEFINED, NULL, 0,
+ (void *)rej, sizeof *rej);
+
+out:
+ kfree(rep_param);
+ kfree(rsp);
+ kfree(rej);
+
+ return ret;
+}
+
+static void srpt_cm_rej_recv(struct ib_cm_id *cm_id)
+{
+ printk(KERN_INFO "Received IB REJ for cm_id %p.\n", cm_id);
+ srpt_drain_channel(cm_id);
+}
+
+/**
+ * srpt_cm_rtu_recv() - Process an IB_CM_RTU_RECEIVED or USER_ESTABLISHED event.
+ *
+ * An IB_CM_RTU_RECEIVED message indicates that the connection is established
+ * and that the recipient may begin transmitting (RTU = ready to use).
+ */
+static void srpt_cm_rtu_recv(struct ib_cm_id *cm_id)
+{
+ struct srpt_rdma_ch *ch;
+ int ret;
+
+ ch = srpt_find_channel(cm_id->context, cm_id);
+ BUG_ON(!ch);
+
+ if (srpt_test_and_set_ch_state(ch, CH_CONNECTING, CH_LIVE)) {
+ struct srpt_recv_ioctx *ioctx, *ioctx_tmp;
+
+ ret = srpt_ch_qp_rts(ch, ch->qp);
+
+ list_for_each_entry_safe(ioctx, ioctx_tmp, &ch->cmd_wait_list,
+ wait_list) {
+ list_del(&ioctx->wait_list);
+ srpt_handle_new_iu(ch, ioctx, NULL);
+ }
+ if (ret)
+ srpt_close_ch(ch);
+ }
+}
+
+static void srpt_cm_timewait_exit(struct ib_cm_id *cm_id)
+{
+ printk(KERN_INFO "Received IB TimeWait exit for cm_id %p.\n", cm_id);
+ srpt_drain_channel(cm_id);
+}
+
+static void srpt_cm_rep_error(struct ib_cm_id *cm_id)
+{
+ printk(KERN_INFO "Received IB REP error for cm_id %p.\n", cm_id);
+ srpt_drain_channel(cm_id);
+}
+
+/**
+ * srpt_cm_dreq_recv() - Process reception of a DREQ message.
+ */
+static void srpt_cm_dreq_recv(struct ib_cm_id *cm_id)
+{
+ struct srpt_rdma_ch *ch;
+ unsigned long flags;
+ bool send_drep = false;
+
+ ch = srpt_find_channel(cm_id->context, cm_id);
+ BUG_ON(!ch);
+
+ pr_debug("cm_id= %p ch->state= %d\n", cm_id, srpt_get_ch_state(ch));
+
+ spin_lock_irqsave(&ch->spinlock, flags);
+ switch (ch->state) {
+ case CH_CONNECTING:
+ case CH_LIVE:
+ send_drep = true;
+ ch->state = CH_DISCONNECTING;
+ break;
+ case CH_DISCONNECTING:
+ case CH_DRAINING:
+ case CH_RELEASING:
+ WARN(true, "unexpected channel state %d\n", ch->state);
+ break;
+ }
+ spin_unlock_irqrestore(&ch->spinlock, flags);
+
+ if (send_drep) {
+ if (ib_send_cm_drep(ch->cm_id, NULL, 0) < 0)
+ printk(KERN_ERR "Sending IB DREP failed.\n");
+ printk(KERN_INFO "Received DREQ and sent DREP for session %s.\n",
+ ch->sess_name);
+ }
+}
+
+/**
+ * srpt_cm_drep_recv() - Process reception of a DREP message.
+ */
+static void srpt_cm_drep_recv(struct ib_cm_id *cm_id)
+{
+ printk(KERN_INFO "Received InfiniBand DREP message for cm_id %p.\n",
+ cm_id);
+ srpt_drain_channel(cm_id);
+}
+
+/**
+ * srpt_cm_handler() - IB connection manager callback function.
+ *
+ * A non-zero return value will cause the caller destroy the CM ID.
+ *
+ * Note: srpt_cm_handler() must only return a non-zero value when transferring
+ * ownership of the cm_id to a channel by srpt_cm_req_recv() failed. Returning
+ * a non-zero value in any other case will trigger a race with the
+ * ib_destroy_cm_id() call in srpt_release_channel().
+ */
+static int srpt_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
+{
+ int ret;
+
+ ret = 0;
+ switch (event->event) {
+ case IB_CM_REQ_RECEIVED:
+ ret = srpt_cm_req_recv(cm_id, &event->param.req_rcvd,
+ event->private_data);
+ break;
+ case IB_CM_REJ_RECEIVED:
+ srpt_cm_rej_recv(cm_id);
+ break;
+ case IB_CM_RTU_RECEIVED:
+ case IB_CM_USER_ESTABLISHED:
+ srpt_cm_rtu_recv(cm_id);
+ break;
+ case IB_CM_DREQ_RECEIVED:
+ srpt_cm_dreq_recv(cm_id);
+ break;
+ case IB_CM_DREP_RECEIVED:
+ srpt_cm_drep_recv(cm_id);
+ break;
+ case IB_CM_TIMEWAIT_EXIT:
+ srpt_cm_timewait_exit(cm_id);
+ break;
+ case IB_CM_REP_ERROR:
+ srpt_cm_rep_error(cm_id);
+ break;
+ case IB_CM_DREQ_ERROR:
+ printk(KERN_INFO "Received IB DREQ ERROR event.\n");
+ break;
+ case IB_CM_MRA_RECEIVED:
+ printk(KERN_INFO "Received IB MRA event\n");
+ break;
+ default:
+ printk(KERN_ERR "received unrecognized IB CM event %d\n",
+ event->event);
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * srpt_perform_rdmas() - Perform IB RDMA.
+ *
+ * Returns zero upon success or a negative number upon failure.
+ */
+static int srpt_perform_rdmas(struct srpt_rdma_ch *ch,
+ struct srpt_send_ioctx *ioctx)
+{
+ struct ib_send_wr wr;
+ struct ib_send_wr *bad_wr;
+ struct rdma_iu *riu;
+ int i;
+ int ret;
+ int sq_wr_avail;
+ enum dma_data_direction dir;
+ const int n_rdma = ioctx->n_rdma;
+
+ dir = ioctx->cmd.data_direction;
+ if (dir == DMA_TO_DEVICE) {
+ /* write */
+ ret = -ENOMEM;
+ sq_wr_avail = atomic_sub_return(n_rdma, &ch->sq_wr_avail);
+ if (sq_wr_avail < 0) {
+ printk(KERN_WARNING "IB send queue full (needed %d)\n",
+ n_rdma);
+ goto out;
+ }
+ }
+
+ ioctx->rdma_aborted = false;
+ ret = 0;
+ riu = ioctx->rdma_ius;
+ memset(&wr, 0, sizeof wr);
+
+ for (i = 0; i < n_rdma; ++i, ++riu) {
+ if (dir == DMA_FROM_DEVICE) {
+ wr.opcode = IB_WR_RDMA_WRITE;
+ wr.wr_id = encode_wr_id(i == n_rdma - 1 ?
+ SRPT_RDMA_WRITE_LAST :
+ SRPT_RDMA_MID,
+ ioctx->ioctx.index);
+ } else {
+ wr.opcode = IB_WR_RDMA_READ;
+ wr.wr_id = encode_wr_id(i == n_rdma - 1 ?
+ SRPT_RDMA_READ_LAST :
+ SRPT_RDMA_MID,
+ ioctx->ioctx.index);
+ }
+ wr.next = NULL;
+ wr.wr.rdma.remote_addr = riu->raddr;
+ wr.wr.rdma.rkey = riu->rkey;
+ wr.num_sge = riu->sge_cnt;
+ wr.sg_list = riu->sge;
+
+ /* only get completion event for the last rdma write */
+ if (i == (n_rdma - 1) && dir == DMA_TO_DEVICE)
+ wr.send_flags = IB_SEND_SIGNALED;
+
+ ret = ib_post_send(ch->qp, &wr, &bad_wr);
+ if (ret)
+ break;
+ }
+
+ if (ret)
+ printk(KERN_ERR "%s[%d]: ib_post_send() returned %d for %d/%d",
+ __func__, __LINE__, ret, i, n_rdma);
+ if (ret && i > 0) {
+ wr.num_sge = 0;
+ wr.wr_id = encode_wr_id(SRPT_RDMA_ABORT, ioctx->ioctx.index);
+ wr.send_flags = IB_SEND_SIGNALED;
+ while (ch->state == CH_LIVE &&
+ ib_post_send(ch->qp, &wr, &bad_wr) != 0) {
+ printk(KERN_INFO "Trying to abort failed RDMA transfer [%d]",
+ ioctx->ioctx.index);
+ msleep(1000);
+ }
+ while (ch->state != CH_RELEASING && !ioctx->rdma_aborted) {
+ printk(KERN_INFO "Waiting until RDMA abort finished [%d]",
+ ioctx->ioctx.index);
+ msleep(1000);
+ }
+ }
+out:
+ if (unlikely(dir == DMA_TO_DEVICE && ret < 0))
+ atomic_add(n_rdma, &ch->sq_wr_avail);
+ return ret;
+}
+
+/**
+ * srpt_xfer_data() - Start data transfer from initiator to target.
+ */
+static int srpt_xfer_data(struct srpt_rdma_ch *ch,
+ struct srpt_send_ioctx *ioctx)
+{
+ int ret;
+
+ ret = srpt_map_sg_to_ib_sge(ch, ioctx);
+ if (ret) {
+ printk(KERN_ERR "%s[%d] ret=%d\n", __func__, __LINE__, ret);
+ goto out;
+ }
+
+ ret = srpt_perform_rdmas(ch, ioctx);
+ if (ret) {
+ if (ret == -EAGAIN || ret == -ENOMEM)
+ printk(KERN_INFO "%s[%d] queue full -- ret=%d\n",
+ __func__, __LINE__, ret);
+ else
+ printk(KERN_ERR "%s[%d] fatal error -- ret=%d\n",
+ __func__, __LINE__, ret);
+ goto out_unmap;
+ }
+
+out:
+ return ret;
+out_unmap:
+ srpt_unmap_sg_to_ib_sge(ch, ioctx);
+ goto out;
+}
+
+static int srpt_write_pending_status(struct se_cmd *se_cmd)
+{
+ struct srpt_send_ioctx *ioctx;
+
+ ioctx = container_of(se_cmd, struct srpt_send_ioctx, cmd);
+ return srpt_get_cmd_state(ioctx) == SRPT_STATE_NEED_DATA;
+}
+
+/*
+ * srpt_write_pending() - Start data transfer from initiator to target (write).
+ */
+static int srpt_write_pending(struct se_cmd *se_cmd)
+{
+ struct srpt_rdma_ch *ch;
+ struct srpt_send_ioctx *ioctx;
+ enum srpt_command_state new_state;
+ enum rdma_ch_state ch_state;
+ int ret;
+
+ ioctx = container_of(se_cmd, struct srpt_send_ioctx, cmd);
+
+ new_state = srpt_set_cmd_state(ioctx, SRPT_STATE_NEED_DATA);
+ WARN_ON(new_state == SRPT_STATE_DONE);
+
+ ch = ioctx->ch;
+ BUG_ON(!ch);
+
+ ch_state = srpt_get_ch_state(ch);
+ switch (ch_state) {
+ case CH_CONNECTING:
+ WARN(true, "unexpected channel state %d\n", ch_state);
+ ret = -EINVAL;
+ goto out;
+ case CH_LIVE:
+ break;
+ case CH_DISCONNECTING:
+ case CH_DRAINING:
+ case CH_RELEASING:
+ pr_debug("cmd with tag %lld: channel disconnecting\n",
+ ioctx->tag);
+ srpt_set_cmd_state(ioctx, SRPT_STATE_DATA_IN);
+ ret = -EINVAL;
+ goto out;
+ }
+ ret = srpt_xfer_data(ch, ioctx);
+
+out:
+ return ret;
+}
+
+static u8 tcm_to_srp_tsk_mgmt_status(const int tcm_mgmt_status)
+{
+ switch (tcm_mgmt_status) {
+ case TMR_FUNCTION_COMPLETE:
+ return SRP_TSK_MGMT_SUCCESS;
+ case TMR_FUNCTION_REJECTED:
+ return SRP_TSK_MGMT_FUNC_NOT_SUPP;
+ }
+ return SRP_TSK_MGMT_FAILED;
+}
+
+/**
+ * srpt_queue_response() - Transmits the response to a SCSI command.
+ *
+ * Callback function called by the TCM core. Must not block since it can be
+ * invoked on the context of the IB completion handler.
+ */
+static int srpt_queue_response(struct se_cmd *cmd)
+{
+ struct srpt_rdma_ch *ch;
+ struct srpt_send_ioctx *ioctx;
+ enum srpt_command_state state;
+ unsigned long flags;
+ int ret;
+ enum dma_data_direction dir;
+ int resp_len;
+ u8 srp_tm_status;
+
+ ret = 0;
+
+ ioctx = container_of(cmd, struct srpt_send_ioctx, cmd);
+ ch = ioctx->ch;
+ BUG_ON(!ch);
+
+ spin_lock_irqsave(&ioctx->spinlock, flags);
+ state = ioctx->state;
+ switch (state) {
+ case SRPT_STATE_NEW:
+ case SRPT_STATE_DATA_IN:
+ ioctx->state = SRPT_STATE_CMD_RSP_SENT;
+ break;
+ case SRPT_STATE_MGMT:
+ ioctx->state = SRPT_STATE_MGMT_RSP_SENT;
+ break;
+ default:
+ WARN(true, "ch %p; cmd %d: unexpected command state %d\n",
+ ch, ioctx->ioctx.index, ioctx->state);
+ break;
+ }
+ spin_unlock_irqrestore(&ioctx->spinlock, flags);
+
+ if (unlikely(transport_check_aborted_status(&ioctx->cmd, false)
+ || WARN_ON_ONCE(state == SRPT_STATE_CMD_RSP_SENT))) {
+ atomic_inc(&ch->req_lim_delta);
+ srpt_abort_cmd(ioctx);
+ goto out;
+ }
+
+ dir = ioctx->cmd.data_direction;
+
+ /* For read commands, transfer the data to the initiator. */
+ if (dir == DMA_FROM_DEVICE && ioctx->cmd.data_length &&
+ !ioctx->queue_status_only) {
+ ret = srpt_xfer_data(ch, ioctx);
+ if (ret) {
+ printk(KERN_ERR "xfer_data failed for tag %llu\n",
+ ioctx->tag);
+ goto out;
+ }
+ }
+
+ if (state != SRPT_STATE_MGMT)
+ resp_len = srpt_build_cmd_rsp(ch, ioctx, ioctx->tag,
+ cmd->scsi_status);
+ else {
+ srp_tm_status
+ = tcm_to_srp_tsk_mgmt_status(cmd->se_tmr_req->response);
+ resp_len = srpt_build_tskmgmt_rsp(ch, ioctx, srp_tm_status,
+ ioctx->tag);
+ }
+ ret = srpt_post_send(ch, ioctx, resp_len);
+ if (ret) {
+ printk(KERN_ERR "sending cmd response failed for tag %llu\n",
+ ioctx->tag);
+ srpt_unmap_sg_to_ib_sge(ch, ioctx);
+ srpt_set_cmd_state(ioctx, SRPT_STATE_DONE);
+ kref_put(&ioctx->kref, srpt_put_send_ioctx_kref);
+ }
+
+out:
+ return ret;
+}
+
+static int srpt_queue_status(struct se_cmd *cmd)
+{
+ struct srpt_send_ioctx *ioctx;
+
+ ioctx = container_of(cmd, struct srpt_send_ioctx, cmd);
+ BUG_ON(ioctx->sense_data != cmd->sense_buffer);
+ if (cmd->se_cmd_flags &
+ (SCF_TRANSPORT_TASK_SENSE | SCF_EMULATED_TASK_SENSE))
+ WARN_ON(cmd->scsi_status != SAM_STAT_CHECK_CONDITION);
+ ioctx->queue_status_only = true;
+ return srpt_queue_response(cmd);
+}
+
+static void srpt_refresh_port_work(struct work_struct *work)
+{
+ struct srpt_port *sport = container_of(work, struct srpt_port, work);
+
+ srpt_refresh_port(sport);
+}
+
+static int srpt_ch_list_empty(struct srpt_device *sdev)
+{
+ int res;
+
+ spin_lock_irq(&sdev->spinlock);
+ res = list_empty(&sdev->rch_list);
+ spin_unlock_irq(&sdev->spinlock);
+
+ return res;
+}
+
+/**
+ * srpt_release_sdev() - Free the channel resources associated with a target.
+ */
+static int srpt_release_sdev(struct srpt_device *sdev)
+{
+ struct srpt_rdma_ch *ch, *tmp_ch;
+ int res;
+
+ WARN_ON_ONCE(irqs_disabled());
+
+ BUG_ON(!sdev);
+
+ spin_lock_irq(&sdev->spinlock);
+ list_for_each_entry_safe(ch, tmp_ch, &sdev->rch_list, list)
+ __srpt_close_ch(ch);
+ spin_unlock_irq(&sdev->spinlock);
+
+ res = wait_event_interruptible(sdev->ch_releaseQ,
+ srpt_ch_list_empty(sdev));
+ if (res)
+ printk(KERN_ERR "%s: interrupted.\n", __func__);
+
+ return 0;
+}
+
+static struct srpt_port *__srpt_lookup_port(const char *name)
+{
+ struct ib_device *dev;
+ struct srpt_device *sdev;
+ struct srpt_port *sport;
+ int i;
+
+ list_for_each_entry(sdev, &srpt_dev_list, list) {
+ dev = sdev->device;
+ if (!dev)
+ continue;
+
+ for (i = 0; i < dev->phys_port_cnt; i++) {
+ sport = &sdev->port[i];
+
+ if (!strcmp(sport->port_guid, name))
+ return sport;
+ }
+ }
+
+ return NULL;
+}
+
+static struct srpt_port *srpt_lookup_port(const char *name)
+{
+ struct srpt_port *sport;
+
+ spin_lock(&srpt_dev_lock);
+ sport = __srpt_lookup_port(name);
+ spin_unlock(&srpt_dev_lock);
+
+ return sport;
+}
+
+/**
+ * srpt_add_one() - Infiniband device addition callback function.
+ */
+static void srpt_add_one(struct ib_device *device)
+{
+ struct srpt_device *sdev;
+ struct srpt_port *sport;
+ struct ib_srq_init_attr srq_attr;
+ int i;
+
+ pr_debug("device = %p, device->dma_ops = %p\n", device,
+ device->dma_ops);
+
+ sdev = kzalloc(sizeof *sdev, GFP_KERNEL);
+ if (!sdev)
+ goto err;
+
+ sdev->device = device;
+ INIT_LIST_HEAD(&sdev->rch_list);
+ init_waitqueue_head(&sdev->ch_releaseQ);
+ spin_lock_init(&sdev->spinlock);
+
+ if (ib_query_device(device, &sdev->dev_attr))
+ goto free_dev;
+
+ sdev->pd = ib_alloc_pd(device);
+ if (IS_ERR(sdev->pd))
+ goto free_dev;
+
+ sdev->mr = ib_get_dma_mr(sdev->pd, IB_ACCESS_LOCAL_WRITE);
+ if (IS_ERR(sdev->mr))
+ goto err_pd;
+
+ sdev->srq_size = min(srpt_srq_size, sdev->dev_attr.max_srq_wr);
+
+ srq_attr.event_handler = srpt_srq_event;
+ srq_attr.srq_context = (void *)sdev;
+ srq_attr.attr.max_wr = sdev->srq_size;
+ srq_attr.attr.max_sge = 1;
+ srq_attr.attr.srq_limit = 0;
+
+ sdev->srq = ib_create_srq(sdev->pd, &srq_attr);
+ if (IS_ERR(sdev->srq))
+ goto err_mr;
+
+ pr_debug("%s: create SRQ #wr= %d max_allow=%d dev= %s\n",
+ __func__, sdev->srq_size, sdev->dev_attr.max_srq_wr,
+ device->name);
+
+ if (!srpt_service_guid)
+ srpt_service_guid = be64_to_cpu(device->node_guid);
+
+ sdev->cm_id = ib_create_cm_id(device, srpt_cm_handler, sdev);
+ if (IS_ERR(sdev->cm_id))
+ goto err_srq;
+
+ /* print out target login information */
+ pr_debug("Target login info: id_ext=%016llx,ioc_guid=%016llx,"
+ "pkey=ffff,service_id=%016llx\n", srpt_service_guid,
+ srpt_service_guid, srpt_service_guid);
+
+ /*
+ * We do not have a consistent service_id (ie. also id_ext of target_id)
+ * to identify this target. We currently use the guid of the first HCA
+ * in the system as service_id; therefore, the target_id will change
+ * if this HCA is gone bad and replaced by different HCA
+ */
+ if (ib_cm_listen(sdev->cm_id, cpu_to_be64(srpt_service_guid), 0, NULL))
+ goto err_cm;
+
+ INIT_IB_EVENT_HANDLER(&sdev->event_handler, sdev->device,
+ srpt_event_handler);
+ if (ib_register_event_handler(&sdev->event_handler))
+ goto err_cm;
+
+ sdev->ioctx_ring = (struct srpt_recv_ioctx **)
+ srpt_alloc_ioctx_ring(sdev, sdev->srq_size,
+ sizeof(*sdev->ioctx_ring[0]),
+ srp_max_req_size, DMA_FROM_DEVICE);
+ if (!sdev->ioctx_ring)
+ goto err_event;
+
+ for (i = 0; i < sdev->srq_size; ++i)
+ srpt_post_recv(sdev, sdev->ioctx_ring[i]);
+
+ WARN_ON(sdev->device->phys_port_cnt
+ > sizeof(sdev->port)/sizeof(sdev->port[0]));
+
+ for (i = 1; i <= sdev->device->phys_port_cnt; i++) {
+ sport = &sdev->port[i - 1];
+ sport->sdev = sdev;
+ sport->port = i;
+ sport->port_attrib.srp_max_rdma_size = DEFAULT_MAX_RDMA_SIZE;
+ sport->port_attrib.srp_max_rsp_size = DEFAULT_MAX_RSP_SIZE;
+ sport->port_attrib.srp_sq_size = DEF_SRPT_SQ_SIZE;
+ INIT_WORK(&sport->work, srpt_refresh_port_work);
+ INIT_LIST_HEAD(&sport->port_acl_list);
+ spin_lock_init(&sport->port_acl_lock);
+
+ if (srpt_refresh_port(sport)) {
+ printk(KERN_ERR "MAD registration failed for %s-%d.\n",
+ srpt_sdev_name(sdev), i);
+ goto err_ring;
+ }
+ snprintf(sport->port_guid, sizeof(sport->port_guid),
+ "0x%016llx%016llx",
+ be64_to_cpu(sport->gid.global.subnet_prefix),
+ be64_to_cpu(sport->gid.global.interface_id));
+ }
+
+ spin_lock(&srpt_dev_lock);
+ list_add_tail(&sdev->list, &srpt_dev_list);
+ spin_unlock(&srpt_dev_lock);
+
+out:
+ ib_set_client_data(device, &srpt_client, sdev);
+ pr_debug("added %s.\n", device->name);
+ return;
+
+err_ring:
+ srpt_free_ioctx_ring((struct srpt_ioctx **)sdev->ioctx_ring, sdev,
+ sdev->srq_size, srp_max_req_size,
+ DMA_FROM_DEVICE);
+err_event:
+ ib_unregister_event_handler(&sdev->event_handler);
+err_cm:
+ ib_destroy_cm_id(sdev->cm_id);
+err_srq:
+ ib_destroy_srq(sdev->srq);
+err_mr:
+ ib_dereg_mr(sdev->mr);
+err_pd:
+ ib_dealloc_pd(sdev->pd);
+free_dev:
+ kfree(sdev);
+err:
+ sdev = NULL;
+ printk(KERN_INFO "%s(%s) failed.\n", __func__, device->name);
+ goto out;
+}
+
+/**
+ * srpt_remove_one() - InfiniBand device removal callback function.
+ */
+static void srpt_remove_one(struct ib_device *device)
+{
+ struct srpt_device *sdev;
+ int i;
+
+ sdev = ib_get_client_data(device, &srpt_client);
+ if (!sdev) {
+ printk(KERN_INFO "%s(%s): nothing to do.\n", __func__,
+ device->name);
+ return;
+ }
+
+ srpt_unregister_mad_agent(sdev);
+
+ ib_unregister_event_handler(&sdev->event_handler);
+
+ /* Cancel any work queued by the just unregistered IB event handler. */
+ for (i = 0; i < sdev->device->phys_port_cnt; i++)
+ cancel_work_sync(&sdev->port[i].work);
+
+ ib_destroy_cm_id(sdev->cm_id);
+
+ /*
+ * Unregistering a target must happen after destroying sdev->cm_id
+ * such that no new SRP_LOGIN_REQ information units can arrive while
+ * destroying the target.
+ */
+ spin_lock(&srpt_dev_lock);
+ list_del(&sdev->list);
+ spin_unlock(&srpt_dev_lock);
+ srpt_release_sdev(sdev);
+
+ ib_destroy_srq(sdev->srq);
+ ib_dereg_mr(sdev->mr);
+ ib_dealloc_pd(sdev->pd);
+
+ srpt_free_ioctx_ring((struct srpt_ioctx **)sdev->ioctx_ring, sdev,
+ sdev->srq_size, srp_max_req_size, DMA_FROM_DEVICE);
+ sdev->ioctx_ring = NULL;
+ kfree(sdev);
+}
+
+static struct ib_client srpt_client = {
+ .name = DRV_NAME,
+ .add = srpt_add_one,
+ .remove = srpt_remove_one
+};
+
+static int srpt_check_true(struct se_portal_group *se_tpg)
+{
+ return 1;
+}
+
+static int srpt_check_false(struct se_portal_group *se_tpg)
+{
+ return 0;
+}
+
+static char *srpt_get_fabric_name(void)
+{
+ return "srpt";
+}
+
+static u8 srpt_get_fabric_proto_ident(struct se_portal_group *se_tpg)
+{
+ return SCSI_TRANSPORTID_PROTOCOLID_SRP;
+}
+
+static char *srpt_get_fabric_wwn(struct se_portal_group *tpg)
+{
+ struct srpt_port *sport = container_of(tpg, struct srpt_port, port_tpg_1);
+
+ return sport->port_guid;
+}
+
+static u16 srpt_get_tag(struct se_portal_group *tpg)
+{
+ return 1;
+}
+
+static u32 srpt_get_default_depth(struct se_portal_group *se_tpg)
+{
+ return 1;
+}
+
+static u32 srpt_get_pr_transport_id(struct se_portal_group *se_tpg,
+ struct se_node_acl *se_nacl,
+ struct t10_pr_registration *pr_reg,
+ int *format_code, unsigned char *buf)
+{
+ struct srpt_node_acl *nacl;
+ struct spc_rdma_transport_id *tr_id;
+
+ nacl = container_of(se_nacl, struct srpt_node_acl, nacl);
+ tr_id = (void *)buf;
+ tr_id->protocol_identifier = SCSI_TRANSPORTID_PROTOCOLID_SRP;
+ memcpy(tr_id->i_port_id, nacl->i_port_id, sizeof(tr_id->i_port_id));
+ return sizeof(*tr_id);
+}
+
+static u32 srpt_get_pr_transport_id_len(struct se_portal_group *se_tpg,
+ struct se_node_acl *se_nacl,
+ struct t10_pr_registration *pr_reg,
+ int *format_code)
+{
+ *format_code = 0;
+ return sizeof(struct spc_rdma_transport_id);
+}
+
+static char *srpt_parse_pr_out_transport_id(struct se_portal_group *se_tpg,
+ const char *buf, u32 *out_tid_len,
+ char **port_nexus_ptr)
+{
+ struct spc_rdma_transport_id *tr_id;
+
+ *port_nexus_ptr = NULL;
+ *out_tid_len = sizeof(struct spc_rdma_transport_id);
+ tr_id = (void *)buf;
+ return (char *)tr_id->i_port_id;
+}
+
+static struct se_node_acl *srpt_alloc_fabric_acl(struct se_portal_group *se_tpg)
+{
+ struct srpt_node_acl *nacl;
+
+ nacl = kzalloc(sizeof(struct srpt_node_acl), GFP_KERNEL);
+ if (!nacl) {
+ printk(KERN_ERR "Unable to alocate struct srpt_node_acl\n");
+ return NULL;
+ }
+
+ return &nacl->nacl;
+}
+
+static void srpt_release_fabric_acl(struct se_portal_group *se_tpg,
+ struct se_node_acl *se_nacl)
+{
+ struct srpt_node_acl *nacl;
+
+ nacl = container_of(se_nacl, struct srpt_node_acl, nacl);
+ kfree(nacl);
+}
+
+static u32 srpt_tpg_get_inst_index(struct se_portal_group *se_tpg)
+{
+ return 1;
+}
+
+static void srpt_release_cmd(struct se_cmd *se_cmd)
+{
+}
+
+/**
+ * srpt_shutdown_session() - Whether or not a session may be shut down.
+ */
+static int srpt_shutdown_session(struct se_session *se_sess)
+{
+ return true;
+}
+
+/**
+ * srpt_close_session() - Forcibly close a session.
+ *
+ * Callback function invoked by the TCM core to clean up sessions associated
+ * with a node ACL when the user invokes
+ * rmdir /sys/kernel/config/target/$driver/$port/$tpg/acls/$i_port_id
+ */
+static void srpt_close_session(struct se_session *se_sess)
+{
+ DECLARE_COMPLETION_ONSTACK(release_done);
+ struct srpt_rdma_ch *ch;
+ struct srpt_device *sdev;
+ int res;
+
+ ch = se_sess->fabric_sess_ptr;
+ WARN_ON(ch->sess != se_sess);
+
+ pr_debug("ch %p state %d\n", ch, srpt_get_ch_state(ch));
+
+ sdev = ch->sport->sdev;
+ spin_lock_irq(&sdev->spinlock);
+ BUG_ON(ch->release_done);
+ ch->release_done = &release_done;
+ __srpt_close_ch(ch);
+ spin_unlock_irq(&sdev->spinlock);
+
+ res = wait_for_completion_timeout(&release_done, 60 * HZ);
+ WARN_ON(res <= 0);
+}
+
+/**
+ * To do: Find out whether stop_session() has a meaning for transports
+ * other than iSCSI.
+ */
+static void srpt_stop_session(struct se_session *se_sess, int sess_sleep,
+ int conn_sleep)
+{
+}
+
+static void srpt_reset_nexus(struct se_session *sess)
+{
+ printk(KERN_ERR "This is the SRP protocol, not iSCSI\n");
+}
+
+static int srpt_sess_logged_in(struct se_session *se_sess)
+{
+ return true;
+}
+
+/**
+ * srpt_sess_get_index() - Return the value of scsiAttIntrPortIndex (SCSI-MIB).
+ *
+ * A quote from RFC 4455 (SCSI-MIB) about this MIB object:
+ * This object represents an arbitrary integer used to uniquely identify a
+ * particular attached remote initiator port to a particular SCSI target port
+ * within a particular SCSI target device within a particular SCSI instance.
+ */
+static u32 srpt_sess_get_index(struct se_session *se_sess)
+{
+ return 0;
+}
+
+static void srpt_set_default_node_attrs(struct se_node_acl *nacl)
+{
+}
+
+static u32 srpt_get_task_tag(struct se_cmd *se_cmd)
+{
+ struct srpt_send_ioctx *ioctx;
+
+ ioctx = container_of(se_cmd, struct srpt_send_ioctx, cmd);
+ return ioctx->tag;
+}
+
+/* Note: only used from inside debug printk's by the TCM core. */
+static int srpt_get_tcm_cmd_state(struct se_cmd *se_cmd)
+{
+ struct srpt_send_ioctx *ioctx;
+
+ ioctx = container_of(se_cmd, struct srpt_send_ioctx, cmd);
+ return srpt_get_cmd_state(ioctx);
+}
+
+static u16 srpt_set_fabric_sense_len(struct se_cmd *cmd, u32 sense_length)
+{
+ return 0;
+}
+
+static u16 srpt_get_fabric_sense_len(void)
+{
+ return 0;
+}
+
+static int srpt_is_state_remove(struct se_cmd *se_cmd)
+{
+ return 0;
+}
+
+/**
+ * srpt_parse_i_port_id() - Parse an initiator port ID.
+ * @name: ASCII representation of a 128-bit initiator port ID.
+ * @i_port_id: Binary 128-bit port ID.
+ */
+static int srpt_parse_i_port_id(u8 i_port_id[16], const char *name)
+{
+ const char *p;
+ unsigned len, count, leading_zero_bytes;
+ int ret, rc;
+
+ p = name;
+ if (strnicmp(p, "0x", 2) == 0)
+ p += 2;
+ ret = -EINVAL;
+ len = strlen(p);
+ if (len % 2)
+ goto out;
+ count = min(len / 2, 16U);
+ leading_zero_bytes = 16 - count;
+ memset(i_port_id, 0, leading_zero_bytes);
+ rc = hex2bin(i_port_id + leading_zero_bytes, p, count);
+ if (rc < 0)
+ pr_debug("hex2bin failed for srpt_parse_i_port_id: %d\n", rc);
+ ret = 0;
+out:
+ return ret;
+}
+
+/*
+ * configfs callback function invoked for
+ * mkdir /sys/kernel/config/target/$driver/$port/$tpg/acls/$i_port_id
+ */
+static struct se_node_acl *srpt_make_nodeacl(struct se_portal_group *tpg,
+ struct config_group *group,
+ const char *name)
+{
+ struct srpt_port *sport = container_of(tpg, struct srpt_port, port_tpg_1);
+ struct se_node_acl *se_nacl, *se_nacl_new;
+ struct srpt_node_acl *nacl;
+ int ret = 0;
+ u32 nexus_depth = 1;
+ u8 i_port_id[16];
+
+ if (srpt_parse_i_port_id(i_port_id, name) < 0) {
+ printk(KERN_ERR "invalid initiator port ID %s\n", name);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ se_nacl_new = srpt_alloc_fabric_acl(tpg);
+ if (!se_nacl_new) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ /*
+ * nacl_new may be released by core_tpg_add_initiator_node_acl()
+ * when converting a node ACL from demo mode to explict
+ */
+ se_nacl = core_tpg_add_initiator_node_acl(tpg, se_nacl_new, name,
+ nexus_depth);
+ if (IS_ERR(se_nacl)) {
+ ret = PTR_ERR(se_nacl);
+ goto err;
+ }
+ /* Locate our struct srpt_node_acl and set sdev and i_port_id. */
+ nacl = container_of(se_nacl, struct srpt_node_acl, nacl);
+ memcpy(&nacl->i_port_id[0], &i_port_id[0], 16);
+ nacl->sport = sport;
+
+ spin_lock_irq(&sport->port_acl_lock);
+ list_add_tail(&nacl->list, &sport->port_acl_list);
+ spin_unlock_irq(&sport->port_acl_lock);
+
+ return se_nacl;
+err:
+ return ERR_PTR(ret);
+}
+
+/*
+ * configfs callback function invoked for
+ * rmdir /sys/kernel/config/target/$driver/$port/$tpg/acls/$i_port_id
+ */
+static void srpt_drop_nodeacl(struct se_node_acl *se_nacl)
+{
+ struct srpt_node_acl *nacl;
+ struct srpt_device *sdev;
+ struct srpt_port *sport;
+
+ nacl = container_of(se_nacl, struct srpt_node_acl, nacl);
+ sport = nacl->sport;
+ sdev = sport->sdev;
+ spin_lock_irq(&sport->port_acl_lock);
+ list_del(&nacl->list);
+ spin_unlock_irq(&sport->port_acl_lock);
+ core_tpg_del_initiator_node_acl(&sport->port_tpg_1, se_nacl, 1);
+ srpt_release_fabric_acl(NULL, se_nacl);
+}
+
+static ssize_t srpt_tpg_attrib_show_srp_max_rdma_size(
+ struct se_portal_group *se_tpg,
+ char *page)
+{
+ struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);
+
+ return sprintf(page, "%u\n", sport->port_attrib.srp_max_rdma_size);
+}
+
+static ssize_t srpt_tpg_attrib_store_srp_max_rdma_size(
+ struct se_portal_group *se_tpg,
+ const char *page,
+ size_t count)
+{
+ struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);
+ unsigned long val;
+ int ret;
+
+ ret = strict_strtoul(page, 0, &val);
+ if (ret < 0) {
+ pr_err("strict_strtoul() failed with ret: %d\n", ret);
+ return -EINVAL;
+ }
+ if (val > MAX_SRPT_RDMA_SIZE) {
+ pr_err("val: %lu exceeds MAX_SRPT_RDMA_SIZE: %d\n", val,
+ MAX_SRPT_RDMA_SIZE);
+ return -EINVAL;
+ }
+ if (val < DEFAULT_MAX_RDMA_SIZE) {
+ pr_err("val: %lu smaller than DEFAULT_MAX_RDMA_SIZE: %d\n",
+ val, DEFAULT_MAX_RDMA_SIZE);
+ return -EINVAL;
+ }
+ sport->port_attrib.srp_max_rdma_size = val;
+
+ return count;
+}
+
+TF_TPG_ATTRIB_ATTR(srpt, srp_max_rdma_size, S_IRUGO | S_IWUSR);
+
+static ssize_t srpt_tpg_attrib_show_srp_max_rsp_size(
+ struct se_portal_group *se_tpg,
+ char *page)
+{
+ struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);
+
+ return sprintf(page, "%u\n", sport->port_attrib.srp_max_rsp_size);
+}
+
+static ssize_t srpt_tpg_attrib_store_srp_max_rsp_size(
+ struct se_portal_group *se_tpg,
+ const char *page,
+ size_t count)
+{
+ struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);
+ unsigned long val;
+ int ret;
+
+ ret = strict_strtoul(page, 0, &val);
+ if (ret < 0) {
+ pr_err("strict_strtoul() failed with ret: %d\n", ret);
+ return -EINVAL;
+ }
+ if (val > MAX_SRPT_RSP_SIZE) {
+ pr_err("val: %lu exceeds MAX_SRPT_RSP_SIZE: %d\n", val,
+ MAX_SRPT_RSP_SIZE);
+ return -EINVAL;
+ }
+ if (val < MIN_MAX_RSP_SIZE) {
+ pr_err("val: %lu smaller than MIN_MAX_RSP_SIZE: %d\n", val,
+ MIN_MAX_RSP_SIZE);
+ return -EINVAL;
+ }
+ sport->port_attrib.srp_max_rsp_size = val;
+
+ return count;
+}
+
+TF_TPG_ATTRIB_ATTR(srpt, srp_max_rsp_size, S_IRUGO | S_IWUSR);
+
+static ssize_t srpt_tpg_attrib_show_srp_sq_size(
+ struct se_portal_group *se_tpg,
+ char *page)
+{
+ struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);
+
+ return sprintf(page, "%u\n", sport->port_attrib.srp_sq_size);
+}
+
+static ssize_t srpt_tpg_attrib_store_srp_sq_size(
+ struct se_portal_group *se_tpg,
+ const char *page,
+ size_t count)
+{
+ struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);
+ unsigned long val;
+ int ret;
+
+ ret = strict_strtoul(page, 0, &val);
+ if (ret < 0) {
+ pr_err("strict_strtoul() failed with ret: %d\n", ret);
+ return -EINVAL;
+ }
+ if (val > MAX_SRPT_SRQ_SIZE) {
+ pr_err("val: %lu exceeds MAX_SRPT_SRQ_SIZE: %d\n", val,
+ MAX_SRPT_SRQ_SIZE);
+ return -EINVAL;
+ }
+ if (val < MIN_SRPT_SRQ_SIZE) {
+ pr_err("val: %lu smaller than MIN_SRPT_SRQ_SIZE: %d\n", val,
+ MIN_SRPT_SRQ_SIZE);
+ return -EINVAL;
+ }
+ sport->port_attrib.srp_sq_size = val;
+
+ return count;
+}
+
+TF_TPG_ATTRIB_ATTR(srpt, srp_sq_size, S_IRUGO | S_IWUSR);
+
+static struct configfs_attribute *srpt_tpg_attrib_attrs[] = {
+ &srpt_tpg_attrib_srp_max_rdma_size.attr,
+ &srpt_tpg_attrib_srp_max_rsp_size.attr,
+ &srpt_tpg_attrib_srp_sq_size.attr,
+ NULL,
+};
+
+static ssize_t srpt_tpg_show_enable(
+ struct se_portal_group *se_tpg,
+ char *page)
+{
+ struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);
+
+ return snprintf(page, PAGE_SIZE, "%d\n", (sport->enabled) ? 1: 0);
+}
+
+static ssize_t srpt_tpg_store_enable(
+ struct se_portal_group *se_tpg,
+ const char *page,
+ size_t count)
+{
+ struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);
+ unsigned long tmp;
+ int ret;
+
+ ret = strict_strtoul(page, 0, &tmp);
+ if (ret < 0) {
+ printk(KERN_ERR "Unable to extract srpt_tpg_store_enable\n");
+ return -EINVAL;
+ }
+
+ if ((tmp != 0) && (tmp != 1)) {
+ printk(KERN_ERR "Illegal value for srpt_tpg_store_enable: %lu\n", tmp);
+ return -EINVAL;
+ }
+ if (tmp == 1)
+ sport->enabled = true;
+ else
+ sport->enabled = false;
+
+ return count;
+}
+
+TF_TPG_BASE_ATTR(srpt, enable, S_IRUGO | S_IWUSR);
+
+static struct configfs_attribute *srpt_tpg_attrs[] = {
+ &srpt_tpg_enable.attr,
+ NULL,
+};
+
+/**
+ * configfs callback invoked for
+ * mkdir /sys/kernel/config/target/$driver/$port/$tpg
+ */
+static struct se_portal_group *srpt_make_tpg(struct se_wwn *wwn,
+ struct config_group *group,
+ const char *name)
+{
+ struct srpt_port *sport = container_of(wwn, struct srpt_port, port_wwn);
+ int res;
+
+ /* Initialize sport->port_wwn and sport->port_tpg_1 */
+ res = core_tpg_register(&srpt_target->tf_ops, &sport->port_wwn,
+ &sport->port_tpg_1, sport, TRANSPORT_TPG_TYPE_NORMAL);
+ if (res)
+ return ERR_PTR(res);
+
+ return &sport->port_tpg_1;
+}
+
+/**
+ * configfs callback invoked for
+ * rmdir /sys/kernel/config/target/$driver/$port/$tpg
+ */
+static void srpt_drop_tpg(struct se_portal_group *tpg)
+{
+ struct srpt_port *sport = container_of(tpg,
+ struct srpt_port, port_tpg_1);
+
+ sport->enabled = false;
+ core_tpg_deregister(&sport->port_tpg_1);
+}
+
+/**
+ * configfs callback invoked for
+ * mkdir /sys/kernel/config/target/$driver/$port
+ */
+static struct se_wwn *srpt_make_tport(struct target_fabric_configfs *tf,
+ struct config_group *group,
+ const char *name)
+{
+ struct srpt_port *sport;
+ int ret;
+
+ sport = srpt_lookup_port(name);
+ pr_debug("make_tport(%s)\n", name);
+ ret = -EINVAL;
+ if (!sport)
+ goto err;
+
+ return &sport->port_wwn;
+
+err:
+ return ERR_PTR(ret);
+}
+
+/**
+ * configfs callback invoked for
+ * rmdir /sys/kernel/config/target/$driver/$port
+ */
+static void srpt_drop_tport(struct se_wwn *wwn)
+{
+ struct srpt_port *sport = container_of(wwn, struct srpt_port, port_wwn);
+
+ pr_debug("drop_tport(%s\n", config_item_name(&sport->port_wwn.wwn_group.cg_item));
+}
+
+static ssize_t srpt_wwn_show_attr_version(struct target_fabric_configfs *tf,
+ char *buf)
+{
+ return scnprintf(buf, PAGE_SIZE, "%s\n", DRV_VERSION);
+}
+
+TF_WWN_ATTR_RO(srpt, version);
+
+static struct configfs_attribute *srpt_wwn_attrs[] = {
+ &srpt_wwn_version.attr,
+ NULL,
+};
+
+static struct target_core_fabric_ops srpt_template = {
+ .get_fabric_name = srpt_get_fabric_name,
+ .get_fabric_proto_ident = srpt_get_fabric_proto_ident,
+ .tpg_get_wwn = srpt_get_fabric_wwn,
+ .tpg_get_tag = srpt_get_tag,
+ .tpg_get_default_depth = srpt_get_default_depth,
+ .tpg_get_pr_transport_id = srpt_get_pr_transport_id,
+ .tpg_get_pr_transport_id_len = srpt_get_pr_transport_id_len,
+ .tpg_parse_pr_out_transport_id = srpt_parse_pr_out_transport_id,
+ .tpg_check_demo_mode = srpt_check_false,
+ .tpg_check_demo_mode_cache = srpt_check_true,
+ .tpg_check_demo_mode_write_protect = srpt_check_true,
+ .tpg_check_prod_mode_write_protect = srpt_check_false,
+ .tpg_alloc_fabric_acl = srpt_alloc_fabric_acl,
+ .tpg_release_fabric_acl = srpt_release_fabric_acl,
+ .tpg_get_inst_index = srpt_tpg_get_inst_index,
+ .release_cmd = srpt_release_cmd,
+ .check_stop_free = srpt_check_stop_free,
+ .shutdown_session = srpt_shutdown_session,
+ .close_session = srpt_close_session,
+ .stop_session = srpt_stop_session,
+ .fall_back_to_erl0 = srpt_reset_nexus,
+ .sess_logged_in = srpt_sess_logged_in,
+ .sess_get_index = srpt_sess_get_index,
+ .sess_get_initiator_sid = NULL,
+ .write_pending = srpt_write_pending,
+ .write_pending_status = srpt_write_pending_status,
+ .set_default_node_attributes = srpt_set_default_node_attrs,
+ .get_task_tag = srpt_get_task_tag,
+ .get_cmd_state = srpt_get_tcm_cmd_state,
+ .queue_data_in = srpt_queue_response,
+ .queue_status = srpt_queue_status,
+ .queue_tm_rsp = srpt_queue_response,
+ .get_fabric_sense_len = srpt_get_fabric_sense_len,
+ .set_fabric_sense_len = srpt_set_fabric_sense_len,
+ .is_state_remove = srpt_is_state_remove,
+ /*
+ * Setup function pointers for generic logic in
+ * target_core_fabric_configfs.c
+ */
+ .fabric_make_wwn = srpt_make_tport,
+ .fabric_drop_wwn = srpt_drop_tport,
+ .fabric_make_tpg = srpt_make_tpg,
+ .fabric_drop_tpg = srpt_drop_tpg,
+ .fabric_post_link = NULL,
+ .fabric_pre_unlink = NULL,
+ .fabric_make_np = NULL,
+ .fabric_drop_np = NULL,
+ .fabric_make_nodeacl = srpt_make_nodeacl,
+ .fabric_drop_nodeacl = srpt_drop_nodeacl,
+};
+
+/**
+ * srpt_init_module() - Kernel module initialization.
+ *
+ * Note: Since ib_register_client() registers callback functions, and since at
+ * least one of these callback functions (srpt_add_one()) calls target core
+ * functions, this driver must be registered with the target core before
+ * ib_register_client() is called.
+ */
+static int __init srpt_init_module(void)
+{
+ int ret;
+
+ ret = -EINVAL;
+ if (srp_max_req_size < MIN_MAX_REQ_SIZE) {
+ printk(KERN_ERR "invalid value %d for kernel module parameter"
+ " srp_max_req_size -- must be at least %d.\n",
+ srp_max_req_size, MIN_MAX_REQ_SIZE);
+ goto out;
+ }
+
+ if (srpt_srq_size < MIN_SRPT_SRQ_SIZE
+ || srpt_srq_size > MAX_SRPT_SRQ_SIZE) {
+ printk(KERN_ERR "invalid value %d for kernel module parameter"
+ " srpt_srq_size -- must be in the range [%d..%d].\n",
+ srpt_srq_size, MIN_SRPT_SRQ_SIZE, MAX_SRPT_SRQ_SIZE);
+ goto out;
+ }
+
+ spin_lock_init(&srpt_dev_lock);
+ INIT_LIST_HEAD(&srpt_dev_list);
+
+ ret = -ENODEV;
+ srpt_target = target_fabric_configfs_init(THIS_MODULE, "srpt");
+ if (!srpt_target) {
+ printk(KERN_ERR "couldn't register\n");
+ goto out;
+ }
+
+ srpt_target->tf_ops = srpt_template;
+
+ /* Enable SG chaining */
+ srpt_target->tf_ops.task_sg_chaining = true;
+
+ /*
+ * Set up default attribute lists.
+ */
+ srpt_target->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = srpt_wwn_attrs;
+ srpt_target->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = srpt_tpg_attrs;
+ srpt_target->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = srpt_tpg_attrib_attrs;
+ srpt_target->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL;
+ srpt_target->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;
+ srpt_target->tf_cit_tmpl.tfc_tpg_nacl_base_cit.ct_attrs = NULL;
+ srpt_target->tf_cit_tmpl.tfc_tpg_nacl_attrib_cit.ct_attrs = NULL;
+ srpt_target->tf_cit_tmpl.tfc_tpg_nacl_auth_cit.ct_attrs = NULL;
+ srpt_target->tf_cit_tmpl.tfc_tpg_nacl_param_cit.ct_attrs = NULL;
+
+ ret = target_fabric_configfs_register(srpt_target);
+ if (ret < 0) {
+ printk(KERN_ERR "couldn't register\n");
+ goto out_free_target;
+ }
+
+ ret = ib_register_client(&srpt_client);
+ if (ret) {
+ printk(KERN_ERR "couldn't register IB client\n");
+ goto out_unregister_target;
+ }
+
+ return 0;
+
+out_unregister_target:
+ target_fabric_configfs_deregister(srpt_target);
+ srpt_target = NULL;
+out_free_target:
+ if (srpt_target)
+ target_fabric_configfs_free(srpt_target);
+out:
+ return ret;
+}
+
+static void __exit srpt_cleanup_module(void)
+{
+ ib_unregister_client(&srpt_client);
+ target_fabric_configfs_deregister(srpt_target);
+ srpt_target = NULL;
+}
+
+module_init(srpt_init_module);
+module_exit(srpt_cleanup_module);
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.h b/drivers/infiniband/ulp/srpt/ib_srpt.h
new file mode 100644
index 000000000000..b4b4bbcd7f16
--- /dev/null
+++ b/drivers/infiniband/ulp/srpt/ib_srpt.h
@@ -0,0 +1,444 @@
+/*
+ * Copyright (c) 2006 - 2009 Mellanox Technology Inc. All rights reserved.
+ * Copyright (C) 2009 - 2010 Bart Van Assche <bvanassche@acm.org>.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef IB_SRPT_H
+#define IB_SRPT_H
+
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/wait.h>
+
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_sa.h>
+#include <rdma/ib_cm.h>
+
+#include <scsi/srp.h>
+
+#include "ib_dm_mad.h"
+
+/*
+ * The prefix the ServiceName field must start with in the device management
+ * ServiceEntries attribute pair. See also the SRP specification.
+ */
+#define SRP_SERVICE_NAME_PREFIX "SRP.T10:"
+
+enum {
+ /*
+ * SRP IOControllerProfile attributes for SRP target ports that have
+ * not been defined in <scsi/srp.h>. Source: section B.7, table B.7
+ * in the SRP specification.
+ */
+ SRP_PROTOCOL = 0x0108,
+ SRP_PROTOCOL_VERSION = 0x0001,
+ SRP_IO_SUBCLASS = 0x609e,
+ SRP_SEND_TO_IOC = 0x01,
+ SRP_SEND_FROM_IOC = 0x02,
+ SRP_RDMA_READ_FROM_IOC = 0x08,
+ SRP_RDMA_WRITE_FROM_IOC = 0x20,
+
+ /*
+ * srp_login_cmd.req_flags bitmasks. See also table 9 in the SRP
+ * specification.
+ */
+ SRP_MTCH_ACTION = 0x03, /* MULTI-CHANNEL ACTION */
+ SRP_LOSOLNT = 0x10, /* logout solicited notification */
+ SRP_CRSOLNT = 0x20, /* credit request solicited notification */
+ SRP_AESOLNT = 0x40, /* asynchronous event solicited notification */
+
+ /*
+ * srp_cmd.sol_nt / srp_tsk_mgmt.sol_not bitmasks. See also tables
+ * 18 and 20 in the SRP specification.
+ */
+ SRP_SCSOLNT = 0x02, /* SCSOLNT = successful solicited notification */
+ SRP_UCSOLNT = 0x04, /* UCSOLNT = unsuccessful solicited notification */
+
+ /*
+ * srp_rsp.sol_not / srp_t_logout.sol_not bitmasks. See also tables
+ * 16 and 22 in the SRP specification.
+ */
+ SRP_SOLNT = 0x01, /* SOLNT = solicited notification */
+
+ /* See also table 24 in the SRP specification. */
+ SRP_TSK_MGMT_SUCCESS = 0x00,
+ SRP_TSK_MGMT_FUNC_NOT_SUPP = 0x04,
+ SRP_TSK_MGMT_FAILED = 0x05,
+
+ /* See also table 21 in the SRP specification. */
+ SRP_CMD_SIMPLE_Q = 0x0,
+ SRP_CMD_HEAD_OF_Q = 0x1,
+ SRP_CMD_ORDERED_Q = 0x2,
+ SRP_CMD_ACA = 0x4,
+
+ SRP_LOGIN_RSP_MULTICHAN_NO_CHAN = 0x0,
+ SRP_LOGIN_RSP_MULTICHAN_TERMINATED = 0x1,
+ SRP_LOGIN_RSP_MULTICHAN_MAINTAINED = 0x2,
+
+ SRPT_DEF_SG_TABLESIZE = 128,
+ SRPT_DEF_SG_PER_WQE = 16,
+
+ MIN_SRPT_SQ_SIZE = 16,
+ DEF_SRPT_SQ_SIZE = 4096,
+ SRPT_RQ_SIZE = 128,
+ MIN_SRPT_SRQ_SIZE = 4,
+ DEFAULT_SRPT_SRQ_SIZE = 4095,
+ MAX_SRPT_SRQ_SIZE = 65535,
+ MAX_SRPT_RDMA_SIZE = 1U << 24,
+ MAX_SRPT_RSP_SIZE = 1024,
+
+ MIN_MAX_REQ_SIZE = 996,
+ DEFAULT_MAX_REQ_SIZE
+ = sizeof(struct srp_cmd)/*48*/
+ + sizeof(struct srp_indirect_buf)/*20*/
+ + 128 * sizeof(struct srp_direct_buf)/*16*/,
+
+ MIN_MAX_RSP_SIZE = sizeof(struct srp_rsp)/*36*/ + 4,
+ DEFAULT_MAX_RSP_SIZE = 256, /* leaves 220 bytes for sense data */
+
+ DEFAULT_MAX_RDMA_SIZE = 65536,
+};
+
+enum srpt_opcode {
+ SRPT_RECV,
+ SRPT_SEND,
+ SRPT_RDMA_MID,
+ SRPT_RDMA_ABORT,
+ SRPT_RDMA_READ_LAST,
+ SRPT_RDMA_WRITE_LAST,
+};
+
+static inline u64 encode_wr_id(u8 opcode, u32 idx)
+{
+ return ((u64)opcode << 32) | idx;
+}
+static inline enum srpt_opcode opcode_from_wr_id(u64 wr_id)
+{
+ return wr_id >> 32;
+}
+static inline u32 idx_from_wr_id(u64 wr_id)
+{
+ return (u32)wr_id;
+}
+
+struct rdma_iu {
+ u64 raddr;
+ u32 rkey;
+ struct ib_sge *sge;
+ u32 sge_cnt;
+ int mem_id;
+};
+
+/**
+ * enum srpt_command_state - SCSI command state managed by SRPT.
+ * @SRPT_STATE_NEW: New command arrived and is being processed.
+ * @SRPT_STATE_NEED_DATA: Processing a write or bidir command and waiting
+ * for data arrival.
+ * @SRPT_STATE_DATA_IN: Data for the write or bidir command arrived and is
+ * being processed.
+ * @SRPT_STATE_CMD_RSP_SENT: SRP_RSP for SRP_CMD has been sent.
+ * @SRPT_STATE_MGMT: Processing a SCSI task management command.
+ * @SRPT_STATE_MGMT_RSP_SENT: SRP_RSP for SRP_TSK_MGMT has been sent.
+ * @SRPT_STATE_DONE: Command processing finished successfully, command
+ * processing has been aborted or command processing
+ * failed.
+ */
+enum srpt_command_state {
+ SRPT_STATE_NEW = 0,
+ SRPT_STATE_NEED_DATA = 1,
+ SRPT_STATE_DATA_IN = 2,
+ SRPT_STATE_CMD_RSP_SENT = 3,
+ SRPT_STATE_MGMT = 4,
+ SRPT_STATE_MGMT_RSP_SENT = 5,
+ SRPT_STATE_DONE = 6,
+};
+
+/**
+ * struct srpt_ioctx - Shared SRPT I/O context information.
+ * @buf: Pointer to the buffer.
+ * @dma: DMA address of the buffer.
+ * @index: Index of the I/O context in its ioctx_ring array.
+ */
+struct srpt_ioctx {
+ void *buf;
+ dma_addr_t dma;
+ uint32_t index;
+};
+
+/**
+ * struct srpt_recv_ioctx - SRPT receive I/O context.
+ * @ioctx: See above.
+ * @wait_list: Node for insertion in srpt_rdma_ch.cmd_wait_list.
+ */
+struct srpt_recv_ioctx {
+ struct srpt_ioctx ioctx;
+ struct list_head wait_list;
+};
+
+/**
+ * struct srpt_send_ioctx - SRPT send I/O context.
+ * @ioctx: See above.
+ * @ch: Channel pointer.
+ * @free_list: Node in srpt_rdma_ch.free_list.
+ * @n_rbuf: Number of data buffers in the received SRP command.
+ * @rbufs: Pointer to SRP data buffer array.
+ * @single_rbuf: SRP data buffer if the command has only a single buffer.
+ * @sg: Pointer to sg-list associated with this I/O context.
+ * @sg_cnt: SG-list size.
+ * @mapped_sg_count: ib_dma_map_sg() return value.
+ * @n_rdma_ius: Number of elements in the rdma_ius array.
+ * @rdma_ius: Array with information about the RDMA mapping.
+ * @tag: Tag of the received SRP information unit.
+ * @spinlock: Protects 'state'.
+ * @state: I/O context state.
+ * @rdma_aborted: If initiating a multipart RDMA transfer failed, whether
+ * the already initiated transfers have finished.
+ * @cmd: Target core command data structure.
+ * @sense_data: SCSI sense data.
+ */
+struct srpt_send_ioctx {
+ struct srpt_ioctx ioctx;
+ struct srpt_rdma_ch *ch;
+ struct kref kref;
+ struct rdma_iu *rdma_ius;
+ struct srp_direct_buf *rbufs;
+ struct srp_direct_buf single_rbuf;
+ struct scatterlist *sg;
+ struct list_head free_list;
+ spinlock_t spinlock;
+ enum srpt_command_state state;
+ bool rdma_aborted;
+ struct se_cmd cmd;
+ struct completion tx_done;
+ u64 tag;
+ int sg_cnt;
+ int mapped_sg_count;
+ u16 n_rdma_ius;
+ u8 n_rdma;
+ u8 n_rbuf;
+ bool queue_status_only;
+ u8 sense_data[SCSI_SENSE_BUFFERSIZE];
+};
+
+/**
+ * enum rdma_ch_state - SRP channel state.
+ * @CH_CONNECTING: QP is in RTR state; waiting for RTU.
+ * @CH_LIVE: QP is in RTS state.
+ * @CH_DISCONNECTING: DREQ has been received; waiting for DREP
+ * or DREQ has been send and waiting for DREP
+ * or .
+ * @CH_DRAINING: QP is in ERR state; waiting for last WQE event.
+ * @CH_RELEASING: Last WQE event has been received; releasing resources.
+ */
+enum rdma_ch_state {
+ CH_CONNECTING,
+ CH_LIVE,
+ CH_DISCONNECTING,
+ CH_DRAINING,
+ CH_RELEASING
+};
+
+/**
+ * struct srpt_rdma_ch - RDMA channel.
+ * @wait_queue: Allows the kernel thread to wait for more work.
+ * @thread: Kernel thread that processes the IB queues associated with
+ * the channel.
+ * @cm_id: IB CM ID associated with the channel.
+ * @qp: IB queue pair used for communicating over this channel.
+ * @cq: IB completion queue for this channel.
+ * @rq_size: IB receive queue size.
+ * @rsp_size IB response message size in bytes.
+ * @sq_wr_avail: number of work requests available in the send queue.
+ * @sport: pointer to the information of the HCA port used by this
+ * channel.
+ * @i_port_id: 128-bit initiator port identifier copied from SRP_LOGIN_REQ.
+ * @t_port_id: 128-bit target port identifier copied from SRP_LOGIN_REQ.
+ * @max_ti_iu_len: maximum target-to-initiator information unit length.
+ * @req_lim: request limit: maximum number of requests that may be sent
+ * by the initiator without having received a response.
+ * @req_lim_delta: Number of credits not yet sent back to the initiator.
+ * @spinlock: Protects free_list and state.
+ * @free_list: Head of list with free send I/O contexts.
+ * @state: channel state. See also enum rdma_ch_state.
+ * @ioctx_ring: Send ring.
+ * @wc: IB work completion array for srpt_process_completion().
+ * @list: Node for insertion in the srpt_device.rch_list list.
+ * @cmd_wait_list: List of SCSI commands that arrived before the RTU event. This
+ * list contains struct srpt_ioctx elements and is protected
+ * against concurrent modification by the cm_id spinlock.
+ * @sess: Session information associated with this SRP channel.
+ * @sess_name: Session name.
+ * @release_work: Allows scheduling of srpt_release_channel().
+ * @release_done: Enables waiting for srpt_release_channel() completion.
+ */
+struct srpt_rdma_ch {
+ wait_queue_head_t wait_queue;
+ struct task_struct *thread;
+ struct ib_cm_id *cm_id;
+ struct ib_qp *qp;
+ struct ib_cq *cq;
+ int rq_size;
+ u32 rsp_size;
+ atomic_t sq_wr_avail;
+ struct srpt_port *sport;
+ u8 i_port_id[16];
+ u8 t_port_id[16];
+ int max_ti_iu_len;
+ atomic_t req_lim;
+ atomic_t req_lim_delta;
+ spinlock_t spinlock;
+ struct list_head free_list;
+ enum rdma_ch_state state;
+ struct srpt_send_ioctx **ioctx_ring;
+ struct ib_wc wc[16];
+ struct list_head list;
+ struct list_head cmd_wait_list;
+ struct se_session *sess;
+ u8 sess_name[36];
+ struct work_struct release_work;
+ struct completion *release_done;
+};
+
+/**
+ * struct srpt_port_attib - Attributes for SRPT port
+ * @srp_max_rdma_size: Maximum size of SRP RDMA transfers for new connections.
+ * @srp_max_rsp_size: Maximum size of SRP response messages in bytes.
+ * @srp_sq_size: Shared receive queue (SRQ) size.
+ */
+struct srpt_port_attrib {
+ u32 srp_max_rdma_size;
+ u32 srp_max_rsp_size;
+ u32 srp_sq_size;
+};
+
+/**
+ * struct srpt_port - Information associated by SRPT with a single IB port.
+ * @sdev: backpointer to the HCA information.
+ * @mad_agent: per-port management datagram processing information.
+ * @enabled: Whether or not this target port is enabled.
+ * @port_guid: ASCII representation of Port GUID
+ * @port: one-based port number.
+ * @sm_lid: cached value of the port's sm_lid.
+ * @lid: cached value of the port's lid.
+ * @gid: cached value of the port's gid.
+ * @port_acl_lock spinlock for port_acl_list:
+ * @work: work structure for refreshing the aforementioned cached values.
+ * @port_tpg_1 Target portal group = 1 data.
+ * @port_wwn: Target core WWN data.
+ * @port_acl_list: Head of the list with all node ACLs for this port.
+ */
+struct srpt_port {
+ struct srpt_device *sdev;
+ struct ib_mad_agent *mad_agent;
+ bool enabled;
+ u8 port_guid[64];
+ u8 port;
+ u16 sm_lid;
+ u16 lid;
+ union ib_gid gid;
+ spinlock_t port_acl_lock;
+ struct work_struct work;
+ struct se_portal_group port_tpg_1;
+ struct se_wwn port_wwn;
+ struct list_head port_acl_list;
+ struct srpt_port_attrib port_attrib;
+};
+
+/**
+ * struct srpt_device - Information associated by SRPT with a single HCA.
+ * @device: Backpointer to the struct ib_device managed by the IB core.
+ * @pd: IB protection domain.
+ * @mr: L_Key (local key) with write access to all local memory.
+ * @srq: Per-HCA SRQ (shared receive queue).
+ * @cm_id: Connection identifier.
+ * @dev_attr: Attributes of the InfiniBand device as obtained during the
+ * ib_client.add() callback.
+ * @srq_size: SRQ size.
+ * @ioctx_ring: Per-HCA SRQ.
+ * @rch_list: Per-device channel list -- see also srpt_rdma_ch.list.
+ * @ch_releaseQ: Enables waiting for removal from rch_list.
+ * @spinlock: Protects rch_list and tpg.
+ * @port: Information about the ports owned by this HCA.
+ * @event_handler: Per-HCA asynchronous IB event handler.
+ * @list: Node in srpt_dev_list.
+ */
+struct srpt_device {
+ struct ib_device *device;
+ struct ib_pd *pd;
+ struct ib_mr *mr;
+ struct ib_srq *srq;
+ struct ib_cm_id *cm_id;
+ struct ib_device_attr dev_attr;
+ int srq_size;
+ struct srpt_recv_ioctx **ioctx_ring;
+ struct list_head rch_list;
+ wait_queue_head_t ch_releaseQ;
+ spinlock_t spinlock;
+ struct srpt_port port[2];
+ struct ib_event_handler event_handler;
+ struct list_head list;
+};
+
+/**
+ * struct srpt_node_acl - Per-initiator ACL data (managed via configfs).
+ * @i_port_id: 128-bit SRP initiator port ID.
+ * @sport: port information.
+ * @nacl: Target core node ACL information.
+ * @list: Element of the per-HCA ACL list.
+ */
+struct srpt_node_acl {
+ u8 i_port_id[16];
+ struct srpt_port *sport;
+ struct se_node_acl nacl;
+ struct list_head list;
+};
+
+/*
+ * SRP-releated SCSI persistent reservation definitions.
+ *
+ * See also SPC4r28, section 7.6.1 (Protocol specific parameters introduction).
+ * See also SPC4r28, section 7.6.4.5 (TransportID for initiator ports using
+ * SCSI over an RDMA interface).
+ */
+
+enum {
+ SCSI_TRANSPORTID_PROTOCOLID_SRP = 4,
+};
+
+struct spc_rdma_transport_id {
+ uint8_t protocol_identifier;
+ uint8_t reserved[7];
+ uint8_t i_port_id[16];
+};
+
+#endif /* IB_SRPT_H */
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 32bbd4c77b7c..fd7a0d5bc94d 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/misc/ab8500-ponkey.c b/drivers/input/misc/ab8500-ponkey.c
index 79d901633635..350fd0c385d2 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/wistron_btns.c b/drivers/input/misc/wistron_btns.c
index 52b419348983..e2bdfd4bea70 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/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index de7e8bc17b1f..e6c9931f02c7 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 4b755cb5b38c..1c58aafa523f 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/hp_sdc.c b/drivers/input/serio/hp_sdc.c
index 979c443bf1ef..be3316073ae7 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/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c
index 7f8f538a9806..1df19bb8534a 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 81e338623944..d13143b68b3e 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/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c
index d2b57536feea..46e83ad53f43 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 06cef3ccc63a..3a5ebf452e81 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 9c8d7aa053c5..a0ed668d4d2a 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 d3530f6e8115..9743b24ef9d6 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/sc/init.c b/drivers/isdn/sc/init.c
index ca710ab278ec..023de789f250 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 897a77dfa9d7..9ca28fced2b9 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -396,6 +396,20 @@ config LEDS_TCA6507
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_OT200
+ tristate "LED support for the Bachmann OT200"
+ depends on LEDS_CLASS && HAS_IOMEM
+ help
+ This option enables support for the LEDs on the Bachmann OT200.
+ Say Y to enable LEDs on the Bachmann OT200.
+
config LEDS_TRIGGERS
bool "LED Trigger support"
depends on LEDS_CLASS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 5c9dc4b000d5..1fc6875a8b20 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -28,6 +28,7 @@ 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_OT200) += leds-ot200.o
obj-$(CONFIG_LEDS_FSG) += leds-fsg.o
obj-$(CONFIG_LEDS_PCA955X) += leds-pca955x.o
obj-$(CONFIG_LEDS_DA903X) += leds-da903x.o
@@ -44,6 +45,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-clevo-mail.c b/drivers/leds/leds-clevo-mail.c
index a498135a4e80..1ed1677c916f 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-max8997.c b/drivers/leds/leds-max8997.c
new file mode 100644
index 000000000000..f4c0e37fad1e
--- /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-ot200.c b/drivers/leds/leds-ot200.c
new file mode 100644
index 000000000000..c4646825a620
--- /dev/null
+++ b/drivers/leds/leds-ot200.c
@@ -0,0 +1,171 @@
+/*
+ * Bachmann ot200 leds driver.
+ *
+ * Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ * Christian Gmeiner <christian.gmeiner@gmail.com>
+ *
+ * License: GPL as published by the FSF.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/leds.h>
+#include <linux/io.h>
+#include <linux/module.h>
+
+
+struct ot200_led {
+ struct led_classdev cdev;
+ const char *name;
+ unsigned long port;
+ u8 mask;
+};
+
+/*
+ * The device has three leds on the back panel (led_err, led_init and led_run)
+ * and can handle up to seven leds on the front panel.
+ */
+
+static struct ot200_led leds[] = {
+ {
+ .name = "led_run",
+ .port = 0x5a,
+ .mask = BIT(0),
+ },
+ {
+ .name = "led_init",
+ .port = 0x5a,
+ .mask = BIT(1),
+ },
+ {
+ .name = "led_err",
+ .port = 0x5a,
+ .mask = BIT(2),
+ },
+ {
+ .name = "led_1",
+ .port = 0x49,
+ .mask = BIT(7),
+ },
+ {
+ .name = "led_2",
+ .port = 0x49,
+ .mask = BIT(6),
+ },
+ {
+ .name = "led_3",
+ .port = 0x49,
+ .mask = BIT(5),
+ },
+ {
+ .name = "led_4",
+ .port = 0x49,
+ .mask = BIT(4),
+ },
+ {
+ .name = "led_5",
+ .port = 0x49,
+ .mask = BIT(3),
+ },
+ {
+ .name = "led_6",
+ .port = 0x49,
+ .mask = BIT(2),
+ },
+ {
+ .name = "led_7",
+ .port = 0x49,
+ .mask = BIT(1),
+ }
+};
+
+static DEFINE_SPINLOCK(value_lock);
+
+/*
+ * we need to store the current led states, as it is not
+ * possible to read the current led state via inb().
+ */
+static u8 leds_back;
+static u8 leds_front;
+
+static void ot200_led_brightness_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct ot200_led *led = container_of(led_cdev, struct ot200_led, cdev);
+ u8 *val;
+ unsigned long flags;
+
+ spin_lock_irqsave(&value_lock, flags);
+
+ if (led->port == 0x49)
+ val = &leds_front;
+ else if (led->port == 0x5a)
+ val = &leds_back;
+ else
+ BUG();
+
+ if (value == LED_OFF)
+ *val &= ~led->mask;
+ else
+ *val |= led->mask;
+
+ outb(*val, led->port);
+ spin_unlock_irqrestore(&value_lock, flags);
+}
+
+static int __devinit ot200_led_probe(struct platform_device *pdev)
+{
+ int i;
+ int ret;
+
+ for (i = 0; i < ARRAY_SIZE(leds); i++) {
+
+ leds[i].cdev.name = leds[i].name;
+ leds[i].cdev.brightness_set = ot200_led_brightness_set;
+
+ ret = led_classdev_register(&pdev->dev, &leds[i].cdev);
+ if (ret < 0)
+ goto err;
+ }
+
+ leds_front = 0; /* turn off all front leds */
+ leds_back = BIT(1); /* turn on init led */
+ outb(leds_front, 0x49);
+ outb(leds_back, 0x5a);
+
+ return 0;
+
+err:
+ for (i = i - 1; i >= 0; i--)
+ led_classdev_unregister(&leds[i].cdev);
+
+ return ret;
+}
+
+static int __devexit ot200_led_remove(struct platform_device *pdev)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(leds); i++)
+ led_classdev_unregister(&leds[i].cdev);
+
+ return 0;
+}
+
+static struct platform_driver ot200_led_driver = {
+ .probe = ot200_led_probe,
+ .remove = __devexit_p(ot200_led_remove),
+ .driver = {
+ .name = "leds-ot200",
+ .owner = THIS_MODULE,
+ },
+};
+
+module_platform_driver(ot200_led_driver);
+
+MODULE_AUTHOR("Sebastian A. Siewior <bigeasy@linutronix.de>");
+MODULE_DESCRIPTION("ot200 LED driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:leds-ot200");
diff --git a/drivers/leds/leds-ss4200.c b/drivers/leds/leds-ss4200.c
index 614ebebaaa28..57371e1485ab 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/macintosh/ams/ams-core.c b/drivers/macintosh/ams/ams-core.c
index 399beb1638d1..5c6a2d876562 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 8a712392cd38..b27e530a87a4 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 02367308ff2e..c60d025044ee 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 f84c08029b21..9fb18c147825 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 3921e3bb43c1..9728839f844a 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 5e0090ef4182..801d92d237cf 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 8e9132130142..63cc54289aff 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 da52acb60f52..9417ae2fa0bb 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) {
diff --git a/drivers/media/common/tuners/Kconfig b/drivers/media/common/tuners/Kconfig
index 996302ae210e..4a6d5cef3964 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 196c12a55f9a..8295854ab94b 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 9883617b7862..cb2c98fbad1b 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 fe5c4b8d83ee..5ddce7e326f7 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 2d0e7689c6a2..13381de58a84 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 5eaccdefd0b0..2b60de6c707d 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 000000000000..c89af3cd5eba
--- /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 000000000000..62d0e8ec4e99
--- /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 a4f830bb25d1..f83b0c1ea6c8 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 4e05a67e88c1..62aeedf5c550 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 25a8ea342c46..bca4d75e42d4 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 54be9e6faaaf..6133315fb0e3 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 5d02221e99dd..69e453ef0a1a 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 9f5dba244cb8..2d79b1f5d5eb 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 090cf475f099..2c42d3f01636 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 e29cc2bc113a..602c2e392b17 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 83b497f59e1b..9bd5da4aabb7 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 4fc29730a12c..dfb3a831df45 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 904e5365c78c..dc52b72e1407 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 63cc4004e211..2e67f4459904 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 3d5b6ab7e332..fb881c667c94 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 94340f47562b..454c152ccaa0 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 50cfa8cebb93..640bae4e6a5a 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 e0d5b43772b8..a0d176267470 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 f8ee29e6059c..39e7e583c8c0 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 3acbaa04e1b3..b5ee3ebfcfca 100644
--- a/drivers/media/common/tuners/tuner-xc2028.c
+++ b/drivers/media/common/tuners/tuner-xc2028.c
@@ -24,6 +24,21 @@
#include <linux/dvb/frontend.h>
#include "dvb_frontend.h"
+/* Registers (Write-only) */
+#define XREG_INIT 0x00
+#define XREG_RF_FREQ 0x02
+#define XREG_POWER_DOWN 0x08
+
+/* Registers (Read-only) */
+#define XREG_FREQ_ERROR 0x01
+#define XREG_LOCK 0x02
+#define XREG_VERSION 0x04
+#define XREG_PRODUCT_ID 0x08
+#define XREG_HSYNC_FREQ 0x10
+#define XREG_FRAME_LINES 0x20
+#define XREG_SNR 0x40
+
+#define XREG_ADC_ENV 0x0100
static int debug;
module_param(debug, int, 0644);
@@ -311,7 +326,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;
@@ -885,16 +900,16 @@ static int xc2028_signal(struct dvb_frontend *fe, u16 *strength)
mutex_lock(&priv->lock);
/* Sync Lock Indicator */
- rc = xc2028_get_reg(priv, 0x0002, &frq_lock);
+ rc = xc2028_get_reg(priv, XREG_LOCK, &frq_lock);
if (rc < 0)
goto ret;
/* 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);
+ rc = xc2028_get_reg(priv, XREG_SNR, &signal);
if (rc < 0)
goto ret;
@@ -962,14 +977,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 +1004,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
@@ -1013,9 +1034,9 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
/* CMD= Set frequency */
if (priv->firm_version < 0x0202)
- rc = send_seq(priv, {0x00, 0x02, 0x00, 0x00});
+ rc = send_seq(priv, {0x00, XREG_RF_FREQ, 0x00, 0x00});
else
- rc = send_seq(priv, {0x80, 0x02, 0x00, 0x00});
+ rc = send_seq(priv, {0x80, XREG_RF_FREQ, 0x00, 0x00});
if (rc < 0)
goto ret;
@@ -1084,68 +1105,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 +1142,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 +1194,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);
}
@@ -1207,9 +1216,9 @@ static int xc2028_sleep(struct dvb_frontend *fe)
mutex_lock(&priv->lock);
if (priv->firm_version < 0x0202)
- rc = send_seq(priv, {0x00, 0x08, 0x00, 0x00});
+ rc = send_seq(priv, {0x00, XREG_POWER_DOWN, 0x00, 0x00});
else
- rc = send_seq(priv, {0x80, 0x08, 0x00, 0x00});
+ rc = send_seq(priv, {0x80, XREG_POWER_DOWN, 0x00, 0x00});
priv->cur_fw.type = 0; /* need firmware reload */
diff --git a/drivers/media/common/tuners/xc4000.c b/drivers/media/common/tuners/xc4000.c
index 634f4d9b6c63..68397110b7d9 100644
--- a/drivers/media/common/tuners/xc4000.c
+++ b/drivers/media/common/tuners/xc4000.c
@@ -154,6 +154,8 @@ struct xc4000_priv {
#define XREG_SNR 0x06
#define XREG_VERSION 0x07
#define XREG_PRODUCT_ID 0x08
+#define XREG_SIGNAL_LEVEL 0x0A
+#define XREG_NOISE_LEVEL 0x0B
/*
Basic firmware description. This will remain with
@@ -486,6 +488,16 @@ static int xc_get_quality(struct xc4000_priv *priv, u16 *quality)
return xc4000_readreg(priv, XREG_QUALITY, quality);
}
+static int xc_get_signal_level(struct xc4000_priv *priv, u16 *signal)
+{
+ return xc4000_readreg(priv, XREG_SIGNAL_LEVEL, signal);
+}
+
+static int xc_get_noise_level(struct xc4000_priv *priv, u16 *noise)
+{
+ return xc4000_readreg(priv, XREG_NOISE_LEVEL, noise);
+}
+
static u16 xc_wait_for_lock(struct xc4000_priv *priv)
{
u16 lock_state = 0;
@@ -758,7 +770,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;
@@ -1089,6 +1101,8 @@ static void xc_debug_dump(struct xc4000_priv *priv)
u32 hsync_freq_hz = 0;
u16 frame_lines;
u16 quality;
+ u16 signal = 0;
+ u16 noise = 0;
u8 hw_majorversion = 0, hw_minorversion = 0;
u8 fw_majorversion = 0, fw_minorversion = 0;
@@ -1119,85 +1133,70 @@ static void xc_debug_dump(struct xc4000_priv *priv)
xc_get_quality(priv, &quality);
dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality);
+
+ xc_get_signal_level(priv, &signal);
+ dprintk(1, "*** Signal level = -%ddB (%d)\n", signal >> 8, signal);
+
+ xc_get_noise_level(priv, &noise);
+ dprintk(1, "*** Noise level = %ddB (%d)\n", noise >> 8, noise);
}
-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 +1208,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",
@@ -1451,6 +1452,71 @@ fail:
return ret;
}
+static int xc4000_get_signal(struct dvb_frontend *fe, u16 *strength)
+{
+ struct xc4000_priv *priv = fe->tuner_priv;
+ u16 value = 0;
+ int rc;
+
+ mutex_lock(&priv->lock);
+ rc = xc4000_readreg(priv, XREG_SIGNAL_LEVEL, &value);
+ mutex_unlock(&priv->lock);
+
+ if (rc < 0)
+ goto ret;
+
+ /* Informations from real testing of DVB-T and radio part,
+ coeficient for one dB is 0xff.
+ */
+ tuner_dbg("Signal strength: -%ddB (%05d)\n", value >> 8, value);
+
+ /* all known digital modes */
+ if ((priv->video_standard == XC4000_DTV6) ||
+ (priv->video_standard == XC4000_DTV7) ||
+ (priv->video_standard == XC4000_DTV7_8) ||
+ (priv->video_standard == XC4000_DTV8))
+ goto digital;
+
+ /* Analog mode has NOISE LEVEL important, signal
+ depends only on gain of antenna and amplifiers,
+ but it doesn't tell anything about real quality
+ of reception.
+ */
+ mutex_lock(&priv->lock);
+ rc = xc4000_readreg(priv, XREG_NOISE_LEVEL, &value);
+ mutex_unlock(&priv->lock);
+
+ tuner_dbg("Noise level: %ddB (%05d)\n", value >> 8, value);
+
+ /* highest noise level: 32dB */
+ if (value >= 0x2000) {
+ value = 0;
+ } else {
+ value = ~value << 3;
+ }
+
+ goto ret;
+
+ /* Digital mode has SIGNAL LEVEL important and real
+ noise level is stored in demodulator registers.
+ */
+digital:
+ /* best signal: -50dB */
+ if (value <= 0x3200) {
+ value = 0xffff;
+ /* minimum: -114dB - should be 0x7200 but real zero is 0x713A */
+ } else if (value >= 0x713A) {
+ value = 0;
+ } else {
+ value = ~(value - 0x3200) << 2;
+ }
+
+ret:
+ *strength = value;
+
+ return rc;
+}
+
static int xc4000_get_frequency(struct dvb_frontend *fe, u32 *freq)
{
struct xc4000_priv *priv = fe->tuner_priv;
@@ -1578,6 +1644,7 @@ static const struct dvb_tuner_ops xc4000_tuner_ops = {
.set_params = xc4000_set_params,
.set_analog_params = xc4000_set_analog_params,
.get_frequency = xc4000_get_frequency,
+ .get_rf_strength = xc4000_get_signal,
.get_bandwidth = xc4000_get_bandwidth,
.get_status = xc4000_get_status
};
@@ -1605,7 +1672,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 aa1b2e844d32..296df05b8cda 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 2df1b0214dcd..b1e8c99f469b 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 caa4e18ed1c1..430b3eb11815 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 d88cf2add82b..d70d98f1a571 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 521d69104982..81fab9adc1ca 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 d1e91bc80e78..ce4f85849e7b 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 55e6533f15e9..a609b3a9b146 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 7ea517b7e186..9be65a3b931f 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 2c0acdb4d811..fbbe545a74cb 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) {
+ 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.qpsk.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.qpsk.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.qpsk.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;
}
-
- } else if (fe->ops.info.type == FE_QAM) {
- if ((fe->ops.info.symbol_rate_min &&
- parms->u.qam.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)) {
- 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);
- 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;
@@ -862,32 +904,59 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int i;
+ u32 delsys;
+ delsys = c->delivery_system;
memset(c, 0, sizeof(struct dtv_frontend_properties));
+ c->delivery_system = delsys;
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;
@@ -943,25 +1012,6 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = {
_DTV_CMD(DTV_ISDBT_LAYERC_SEGMENT_COUNT, 1, 0),
_DTV_CMD(DTV_ISDBT_LAYERC_TIME_INTERLEAVING, 1, 0),
- _DTV_CMD(DTV_ISDBT_PARTIAL_RECEPTION, 0, 0),
- _DTV_CMD(DTV_ISDBT_SOUND_BROADCASTING, 0, 0),
- _DTV_CMD(DTV_ISDBT_SB_SUBCHANNEL_ID, 0, 0),
- _DTV_CMD(DTV_ISDBT_SB_SEGMENT_IDX, 0, 0),
- _DTV_CMD(DTV_ISDBT_SB_SEGMENT_COUNT, 0, 0),
- _DTV_CMD(DTV_ISDBT_LAYER_ENABLED, 0, 0),
- _DTV_CMD(DTV_ISDBT_LAYERA_FEC, 0, 0),
- _DTV_CMD(DTV_ISDBT_LAYERA_MODULATION, 0, 0),
- _DTV_CMD(DTV_ISDBT_LAYERA_SEGMENT_COUNT, 0, 0),
- _DTV_CMD(DTV_ISDBT_LAYERA_TIME_INTERLEAVING, 0, 0),
- _DTV_CMD(DTV_ISDBT_LAYERB_FEC, 0, 0),
- _DTV_CMD(DTV_ISDBT_LAYERB_MODULATION, 0, 0),
- _DTV_CMD(DTV_ISDBT_LAYERB_SEGMENT_COUNT, 0, 0),
- _DTV_CMD(DTV_ISDBT_LAYERB_TIME_INTERLEAVING, 0, 0),
- _DTV_CMD(DTV_ISDBT_LAYERC_FEC, 0, 0),
- _DTV_CMD(DTV_ISDBT_LAYERC_MODULATION, 0, 0),
- _DTV_CMD(DTV_ISDBT_LAYERC_SEGMENT_COUNT, 0, 0),
- _DTV_CMD(DTV_ISDBT_LAYERC_TIME_INTERLEAVING, 0, 0),
-
_DTV_CMD(DTV_ISDBS_TS_ID, 1, 0),
_DTV_CMD(DTV_DVBT2_PLP_ID, 1, 0),
@@ -973,6 +1023,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 +1058,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 +1113,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 +1192,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 +1234,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 +1378,168 @@ 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;
+
+ /*
+ * It was reported that some old DVBv5 applications were
+ * filling delivery_system with SYS_UNDEFINED. If this happens,
+ * assume that the application wants to use the first supported
+ * delivery system.
+ */
+ if (c->delivery_system == SYS_UNDEFINED)
+ c->delivery_system = fe->ops.delsys[0];
+
+ 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 +1550,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 +1563,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 +1591,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;
@@ -1551,6 +1725,7 @@ static int dvb_frontend_ioctl_properties(struct file *file,
{
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 err = 0;
@@ -1594,7 +1769,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 +1790,18 @@ 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, if the frontend
+ * is not idle. Otherwise, returns the cached content
+ */
+ if (fepriv->state != FESTATE_IDLE) {
+ err = dtv_get_frontend(fe, NULL);
+ if (err < 0)
+ goto out;
+ }
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 +1820,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 +1951,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 +2146,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 +2302,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 +2371,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 67bbfa728016..d63a8215fe03 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 93d9869e0f15..8766ce8c354d 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 58257165761e..9f203c6767a6 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 3263e9749d09..740f3f496f12 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 bd51a764351b..af176b6ce738 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 c71c77bd7f4b..6a2bf3de8456 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 56cbd3636c31..282a43d648df 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 6252ea6c1904..f619063fa72f 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 b39f14f85e71..1455e2644ab5 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,35 @@ 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 */
+
+ if (state->fe_id)
+ break;
+
+ /* enable DVB-T/T2/C demod on IOE[5] */
ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 5), 0x20);
if (ret)
goto error;
/* attach demod */
- adap->fe_adap[0].fe = dvb_attach(stv0900_attach, &anysee_stv0900_config,
- &adap->dev->i2c_adap, 0);
+ adap->fe_adap[state->fe_id].fe = dvb_attach(cxd2820r_attach,
+ &anysee_cxd2820r_config, &adap->dev->i2c_adap,
+ NULL);
+
+ state->has_ci = true;
break;
}
@@ -842,24 +917,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 +954,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 +971,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 +992,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 +1010,6 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
else
ret = -ENODEV;
-error:
return ret;
}
@@ -969,6 +1039,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 +1275,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 +1304,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 +1332,7 @@ static struct dvb_usb_device_properties anysee_properties = {
}
}
},
- }},
+ } },
}
},
@@ -1087,7 +1362,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 57ee500b8c0e..8ac879431540 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 9cd51ac12076..8a57ed8272de 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 949ea1bc0aae..3940bb0f9ef6 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.h b/drivers/media/dvb/dvb-usb/dib0700.h
index 9bd6d51b3b93..7de125c0b36f 100644
--- a/drivers/media/dvb/dvb-usb/dib0700.h
+++ b/drivers/media/dvb/dvb-usb/dib0700.h
@@ -48,6 +48,8 @@ struct dib0700_state {
u8 disable_streaming_master_mode;
u32 fw_version;
u32 nb_packet_buffer_size;
+ int (*read_status)(struct dvb_frontend *, fe_status_t *);
+ int (*sleep)(struct dvb_frontend* fe);
u8 buf[255];
};
diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c
index 206999476f02..070e82aa53f5 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_core.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_core.c
@@ -834,6 +834,7 @@ static struct usb_driver dib0700_driver = {
module_usb_driver(dib0700_driver);
+MODULE_FIRMWARE("dvb-usb-dib0700-1.20.fw");
MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
MODULE_DESCRIPTION("Driver for devices based on DiBcom DiB0700 - USB bridge");
MODULE_VERSION("1.0");
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c
index f313182eb9d5..f9e966aa26e7 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] = {
{
@@ -2537,19 +3066,25 @@ static struct dib7000p_config stk7070pd_dib7000p_config[2] = {
}
};
-static int stk7070pd_frontend_attach0(struct dvb_usb_adapter *adap)
+static void stk7070pd_init(struct dvb_usb_device *dev)
{
- dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
+ dib0700_set_gpio(dev, GPIO6, GPIO_OUT, 1);
msleep(10);
- 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_set_gpio(dev, GPIO9, GPIO_OUT, 1);
+ dib0700_set_gpio(dev, GPIO4, GPIO_OUT, 1);
+ dib0700_set_gpio(dev, GPIO7, GPIO_OUT, 1);
+ dib0700_set_gpio(dev, GPIO10, GPIO_OUT, 0);
- dib0700_ctrl_clock(adap->dev, 72, 1);
+ dib0700_ctrl_clock(dev, 72, 1);
msleep(10);
- dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
+ dib0700_set_gpio(dev, GPIO10, GPIO_OUT, 1);
+}
+
+static int stk7070pd_frontend_attach0(struct dvb_usb_adapter *adap)
+{
+ stk7070pd_init(adap->dev);
+
msleep(10);
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
@@ -2570,6 +3105,77 @@ static int stk7070pd_frontend_attach1(struct dvb_usb_adapter *adap)
return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
+static int novatd_read_status_override(struct dvb_frontend *fe,
+ fe_status_t *stat)
+{
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+ struct dvb_usb_device *dev = adap->dev;
+ struct dib0700_state *state = dev->priv;
+ int ret;
+
+ ret = state->read_status(fe, stat);
+
+ if (!ret)
+ dib0700_set_gpio(dev, adap->id == 0 ? GPIO1 : GPIO0, GPIO_OUT,
+ !!(*stat & FE_HAS_LOCK));
+
+ return ret;
+}
+
+static int novatd_sleep_override(struct dvb_frontend* fe)
+{
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+ struct dvb_usb_device *dev = adap->dev;
+ struct dib0700_state *state = dev->priv;
+
+ /* turn off LED */
+ dib0700_set_gpio(dev, adap->id == 0 ? GPIO1 : GPIO0, GPIO_OUT, 0);
+
+ return state->sleep(fe);
+}
+
+/**
+ * novatd_frontend_attach - Nova-TD specific attach
+ *
+ * Nova-TD has GPIO0, 1 and 2 for LEDs. So do not fiddle with them except for
+ * information purposes.
+ */
+static int novatd_frontend_attach(struct dvb_usb_adapter *adap)
+{
+ struct dvb_usb_device *dev = adap->dev;
+ struct dib0700_state *st = dev->priv;
+
+ if (adap->id == 0) {
+ stk7070pd_init(dev);
+
+ /* turn the power LED on, the other two off (just in case) */
+ dib0700_set_gpio(dev, GPIO0, GPIO_OUT, 0);
+ dib0700_set_gpio(dev, GPIO1, GPIO_OUT, 0);
+ dib0700_set_gpio(dev, GPIO2, GPIO_OUT, 1);
+
+ if (dib7000p_i2c_enumeration(&dev->i2c_adap, 2, 18,
+ stk7070pd_dib7000p_config) != 0) {
+ err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n",
+ __func__);
+ return -ENODEV;
+ }
+ }
+
+ adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &dev->i2c_adap,
+ adap->id == 0 ? 0x80 : 0x82,
+ &stk7070pd_dib7000p_config[adap->id]);
+
+ if (adap->fe_adap[0].fe == NULL)
+ return -ENODEV;
+
+ st->read_status = adap->fe_adap[0].fe->ops.read_status;
+ adap->fe_adap[0].fe->ops.read_status = novatd_read_status_override;
+ st->sleep = adap->fe_adap[0].fe->ops.sleep;
+ adap->fe_adap[0].fe->ops.sleep = novatd_sleep_override;
+
+ return 0;
+}
+
/* S5H1411 */
static struct s5h1411_config pinnacle_801e_config = {
.output_mode = S5H1411_PARALLEL_OUTPUT,
@@ -2960,6 +3566,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);
@@ -3338,6 +3947,57 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.pid_filter_count = 32,
.pid_filter = stk70x0p_pid_filter,
.pid_filter_ctrl = stk70x0p_pid_filter_ctrl,
+ .frontend_attach = novatd_frontend_attach,
+ .tuner_attach = dib7070p_tuner_attach,
+
+ DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+ }},
+ .size_of_priv = sizeof(struct dib0700_adapter_state),
+ }, {
+ .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 = novatd_frontend_attach,
+ .tuner_attach = dib7070p_tuner_attach,
+
+ DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
+ }},
+ .size_of_priv = sizeof(struct dib0700_adapter_state),
+ }
+ },
+
+ .num_device_descs = 1,
+ .devices = {
+ { "Hauppauge Nova-TD Stick (52009)",
+ { &dib0700_usb_id_table[35], 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 = 2,
+ .adapter = {
+ {
+ .num_frontends = 1,
+ .fe = {{
+ .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+ .pid_filter_count = 32,
+ .pid_filter = stk70x0p_pid_filter,
+ .pid_filter_ctrl = stk70x0p_pid_filter_ctrl,
.frontend_attach = stk7070pd_frontend_attach0,
.tuner_attach = dib7070p_tuner_attach,
@@ -3360,7 +4020,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
}
},
- .num_device_descs = 6,
+ .num_device_descs = 5,
.devices = {
{ "DiBcom STK7070PD reference design",
{ &dib0700_usb_id_table[17], NULL },
@@ -3370,10 +4030,6 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ &dib0700_usb_id_table[18], NULL },
{ NULL },
},
- { "Hauppauge Nova-TD Stick (52009)",
- { &dib0700_usb_id_table[35], NULL },
- { NULL },
- },
{ "Hauppauge Nova-TD-500 (84xxx)",
{ &dib0700_usb_id_table[36], NULL },
{ NULL },
@@ -4025,6 +4681,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 0a9a79820f26..ff34419a4c88 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 17413adec7a1..3d81daa49172 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 ba4a7517354f..ddf282f355b3 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 2d08c9b5128a..d390ddaa5a53 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 ff941d20e6b7..451c5a7adfb2 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 015b4e8af1a5..90a70c66a96e 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 5426267980c7..67957dd99ede 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 67094b879bb4..9f01cd7a6e3f 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 1a876a65ed56..b3fe05bbffc9 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 d1f58371c711..d83df4bb72d3 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 a6341058c4e7..72db6eef4b9c 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 825a8b242e09..38ef0253d3b5 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 56acf8e55d50..e53a1061cb8e 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 2bb8d4cc8d88..5eab468dd904 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 8452eef90322..b8825b18c003 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 489ae8245867..d1a1a1324ef8 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 fd8bbbfa5c59..eb7496eab130 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 8748a61be73d..6fe9793b98b3 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 bd00b04e079d..4fdcd8cb7530 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 4a2d2e6c91ab..ebb5ed7a7783 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 f639f6781551..00a20636df62 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 345311c33383..6bcbcf543b38 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 e53d873f7555..b973fc5a0384 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 e00b2a4a2db6..fa848af6e9b4 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 1539ea1f81ac..a2261ea2cf82 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 1d572940e243..c688b95df486 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 8aff5868a5e1..033cd7ad3ca2 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 5e431ebd089b..53e4d0dbb745 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 c480c839b302..c2a578e1314d 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 0142214b0133..f2a90f990ce3 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 3139558148ba..faba82485086 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 bf9c999aa470..5101f10f2d7a 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 c341d57d5e81..3883c3b31aef 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 ccd05255d527..b48879186537 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 b1dd8acc607a..7e28b4ee7d4f 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 03cab7b547fb..cf0f546aa1d1 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 b85f5011e344..945404991529 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 036480f967b7..caae7f79c837 100644
--- a/drivers/media/dvb/frontends/cxd2820r_core.c
+++ b/drivers/media/dvb/frontends/cxd2820r_core.c
@@ -240,422 +240,239 @@ 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;
+ 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, 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;
+ if (priv->delivery_system == SYS_UNDEFINED)
+ return 0;
- ret = cxd2820r_get_frontend_c(fe, p);
+ 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;
@@ -667,12 +484,12 @@ static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe,
if (priv->last_tune_failed) {
if (priv->delivery_system == SYS_DVBT)
c->delivery_system = SYS_DVBT2;
- else
+ else if (priv->delivery_system == SYS_DVBT2)
c->delivery_system = SYS_DVBT;
}
/* set frontend */
- ret = cxd2820r_set_frontend(fe, p);
+ ret = cxd2820r_set_frontend(fe);
if (ret)
goto error;
@@ -680,6 +497,7 @@ static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe,
/* frontend lock wait loop count */
switch (priv->delivery_system) {
case SYS_DVBT:
+ case SYS_DVBC_ANNEX_A:
i = 20;
break;
case SYS_DVBT2:
@@ -727,9 +545,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 +558,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 95539134efdb..9a9822cad9cd 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 a04f9c810101..1a026239cdcc 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 6548588309f7..3a5759e0d235 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 dc1cb17a6ea7..3b024bfe980a 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 b174d1c78583..224d81e85091 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 13d85244ec16..781dc49de45b 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 437904cbf3e6..af91e0c92339 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 16c526591f36..9dc235aa44b7 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 088e7fadbe3d..ffad181a9692 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 dbb76d75c932..148bf79236fb 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 ce8534ff142e..5ceadc285b3a 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 0179f9474bac..b61b03a6e1ed 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 fe284d5292f5..9ca34f495009 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 617f9eba3a09..39591bb172c1 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 660f80661ed4..863ef3cfab9f 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 5e011474be43..5f484881d7b1 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 7113535844f2..34398738f9bc 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 88e46f4cdbb2..7bf39cda83c5 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 58baf419560c..020981844a86 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 f6431ef827dc..6980ed7b8786 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 a05c32eecdcc..3a58b73eb9b9 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 90bf573308b0..af65d013db11 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);
@@ -1210,7 +1195,7 @@ static int ds3000_set_frontend(struct dvb_frontend *fe,
for (i = 0; i < 30 ; i++) {
ds3000_read_status(fe, &status);
- if (status && FE_HAS_LOCK)
+ if (status & FE_HAS_LOCK)
break;
msleep(10);
@@ -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 62a65efdf8d6..1ab34838221c 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 a7fc7e53a551..dcfc902c8678 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 2414dc6ee5d9..c56fddbf53b7 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 000000000000..a00318190837
--- /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 000000000000..a7a64431364d
--- /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 000000000000..ba16dc3ec2bd
--- /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 1c6fb4b66255..93b086ea7e1c 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 d4bd24eb4700..ccc36bf2deb4 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 9d97f32e690b..c4a908e354e0 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 aa9ccb821fa5..316457584fe7 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 9a517a4bf96d..bc5a82082aaa 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 445fa1068064..36fcf559e361 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 3272881cb112..1d2c47378cf8 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 43971e63baa7..c990d35a13dc 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 bb37ed289a05..2cec8041a106 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 1172b54689f8..4de1d3520cd2 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 c283112051b1..9ae40abfd71a 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 0f867a5055fb..fade566927c3 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 83e6f1a1b700..e20bf13aa860 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 319672f8e1a7..2c3b50e828d7 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 eac20650499f..49ca78d883b1 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 6599b8fea9e9..90ae6c72c0e3 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 38e67accb8c3..5ef921823c15 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 c709ce6771c8..c625b57b4333 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 0e2f61a8978f..f71b06221e14 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 d8adf1e32019..6cc4b7a9dd60 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 3879d2e378aa..2322257c69ae 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 0c6dcb90d168..8352ce1c9556 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 ca0103d5f148..cd2288c07147 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 4b0c99a08a85..a68a64800df7 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 b85eb60a893e..e37274c8f14e 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 4a7c3d842608..f4096ccb226e 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 8408ef877b4b..38565beafe23 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 ed699647050e..a0c3c526b132 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 bc1a8af4f6e1..def88abb30bf 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 0aa3962ff18b..fb5548a82208 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 84d88f33275e..85c157a1fe5e 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 42684bec8883..057b5f8effc0 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 e57ab53e2e27..fdd20c7737b5 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 0ca316d6fffa..7f1badaf0d03 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 ebda41936b90..4aef1877ed42 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 2dca7c8e5148..20b5fa92c53e 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 6ca533ea0f0e..1bff7f457e19 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 a3c34eecdee9..ca1e0d54b69a 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 7f105946a434..71fb63299de7 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 ea485d923550..ae6f22aae677 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 0c37434d19e2..a99205026751 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 f2c8faac6f36..fcfe2e080cb0 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 1b1bf200c55c..ad7c72e8f517 100644
--- a/drivers/media/dvb/frontends/tda18271c2dd.c
+++ b/drivers/media/dvb/frontends/tda18271c2dd.c
@@ -29,7 +29,6 @@
#include <linux/delay.h>
#include <linux/firmware.h>
#include <linux/i2c.h>
-#include <linux/version.h>
#include <asm/div64.h>
#include "dvb_frontend.h"
@@ -1123,55 +1122,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 9369f7442f27..15912c96926a 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 06c94800b940..04bbcc24de0a 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 51f170678650..17750985db0c 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 bcb95c2ef296..029384d1fddd 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 550a07a8a997..bb42b563c42d 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 8d7854c2fb0c..9c17eacaec24 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 81aa984c551f..0903d461b8fa 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 c085e58a94bf..eff9c5fde50a 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 adbbf6d3d044..ac7237891374 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 2ae0afa7756b..ad013e93ed11 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 06da0ddf05a7..1ca6837fbe46 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 f72b137b7652..d480741afd78 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 056419228363..8418c02bcefe 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 80fb51004461..e1f20c236989 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 451641c0c1d2..d980dfb21e5e 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 0f085c3e571b..2db15159d514 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 37c594f82782..654685c9303e 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 3d20719fce1a..6ecbcf614878 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 d85b8512ac30..88b3b2d6cc0e 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 78d32f7e49fc..8b32e282bf5d 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 ca02e9722172..98e524178765 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 3395d1a90516..2cb35c23d2ac 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 d238fb9371a7..b21bcce66708 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 e90192fdde11..5b682cc4c814 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 21260aad1e54..5c45c9d0712d 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 6edc9ba81203..6f9eb94e85b3 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 ccd5f0d8a012..e954781c90bf 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 edadc8449a3d..36ce0611c037 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 3fb76e3834c9..87c1ee13b058 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 d1fab5885061..c54210c7fef9 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 3e9209f84e09..5d9a90ac3a1c 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 8aa4968d57bc..f1b607099b6c 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 0991e1973678..3408685b690c 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 749f67b192e7..86b28579f0c7 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 5991ab60303d..bf867a6b5ea0 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 aee243bb6630..d9b9c6cf83b4 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 ec529b55b040..43fb72291bea 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 329e62f6be76..32add81f8d87 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 be54068b56a8..6ea33e09d63b 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 e393a2bdd49e..11ae2e4c2d03 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 4f5c43d2566c..077d369a0173 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 aeb7f43dfb65..4df4affeea5f 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 2156e786b557..fb3dee2dd845 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 17f8db00435a..3c9431a9f62d 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 2e5cd3100b64..95e630998aaf 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 140fb67e2f89..4cfdd7fa4bbd 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 000000000000..d38fbdd0b25a
--- /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 e51c6163378b..929bbbc16393 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 3bd1de1f585c..23ee05e53949 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 27997a9ceb0d..ca12d3289bfe 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 20bb12d6fbbe..21105bf9594d 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 c6ca870e8b7e..b72f8580e317 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 f5db8b949bc3..f6a930b70c69 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 07322fb75eff..ad95c67a4dba 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 b1d29d09eeae..d6f4bfe09391 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 e7f7a57bf684..b09c5fae489b 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 b303a3f8a9f8..9adada0d7447 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 117f9c4b4cb9..354138804cda 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 23ba5c37c3e4..879f1d839760 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 000000000000..f241702a0f36
--- /dev/null
+++ b/drivers/media/video/as3645a.c
@@ -0,0 +1,905 @@
+/*
+ * 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 <linux/slab.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 8c775c59e120..9fe4519176a4 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 0c3a5ba0e857..81ba9d9d1b52 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 cbdb65c34f21..05c299fa5d79 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 0bcd95303bb0..c37e6acffded 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 5939021d8eba..ff2933ab705f 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 3dd06607aec2..76c301f05095 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 e3952af7e56e..580c8e682392 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 c6333595c6b9..c5171619ac79 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 cd8ff0473184..fda32f52554a 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 5909f2557ab4..1d64af9adf71 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 d93e5ab45fd3..51c5b9ad67d8 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 c6ff32a6137c..349bd9c2aff5 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-fileops.c b/drivers/media/video/cx18/cx18-fileops.c
index 14cb961c22bd..4bfd865a4106 100644
--- a/drivers/media/video/cx18/cx18-fileops.c
+++ b/drivers/media/video/cx18/cx18-fileops.c
@@ -751,20 +751,10 @@ int cx18_v4l2_close(struct file *filp)
CX18_DEBUG_IOCTL("close() of %s\n", s->name);
- v4l2_fh_del(fh);
- v4l2_fh_exit(fh);
-
- /* Easy case first: this stream was never claimed by us */
- if (s->id != id->open_id) {
- kfree(id);
- return 0;
- }
-
- /* 'Unclaim' this stream */
-
- /* Stop radio */
mutex_lock(&cx->serialize_lock);
- if (id->type == CX18_ENC_STREAM_TYPE_RAD) {
+ /* Stop radio */
+ if (id->type == CX18_ENC_STREAM_TYPE_RAD &&
+ v4l2_fh_is_singular_file(filp)) {
/* Closing radio device, return to TV mode */
cx18_mute(cx);
/* Mark that the radio is no longer in use */
@@ -781,10 +771,14 @@ int cx18_v4l2_close(struct file *filp)
}
/* Done! Unmute and continue. */
cx18_unmute(cx);
- cx18_release_stream(s);
- } else {
- cx18_stop_capture(id, 0);
}
+
+ v4l2_fh_del(fh);
+ v4l2_fh_exit(fh);
+
+ /* 'Unclaim' this stream */
+ if (s->id == id->open_id)
+ cx18_stop_capture(id, 0);
kfree(id);
mutex_unlock(&cx->serialize_lock);
return 0;
@@ -810,21 +804,15 @@ static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
item->open_id = cx->open_id++;
filp->private_data = &item->fh;
+ v4l2_fh_add(&item->fh);
- if (item->type == CX18_ENC_STREAM_TYPE_RAD) {
- /* Try to claim this stream */
- if (cx18_claim_stream(item, item->type)) {
- /* No, it's already in use */
- v4l2_fh_exit(&item->fh);
- kfree(item);
- return -EBUSY;
- }
-
+ if (item->type == CX18_ENC_STREAM_TYPE_RAD &&
+ v4l2_fh_is_singular_file(filp)) {
if (!test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) {
if (atomic_read(&cx->ana_capturing) > 0) {
/* switching to radio while capture is
in progress is not polite */
- cx18_release_stream(s);
+ v4l2_fh_del(&item->fh);
v4l2_fh_exit(&item->fh);
kfree(item);
return -EBUSY;
@@ -842,7 +830,6 @@ static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
/* Done! Unmute and continue. */
cx18_unmute(cx);
}
- v4l2_fh_add(&item->fh);
return 0;
}
diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c
index 040aaa87579d..51609d5c88ce 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 bdfd1921e300..1180fdc8d983 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 ae85a7a7bd73..446f692aabb7 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 30d13c15739a..a2c2b7d343ec 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 60b021e79864..875a7ce94736 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(nr, &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 d4457f9488ee..08dd930f882a 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 da9a4a0aab79..7c4e360ba9bc 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 45e14cac4622..96176e9db5a2 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 1c7a4daafecf..8cdee5f78f13 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 6e81f970dc7d..829a41b0c9ef 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 2000bc64c497..e17447554a0d 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 67c4a59bd882..f5c79e53e5a1 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 c3cf08945e4c..19b5499d2624 100644
--- a/drivers/media/video/cx23885/cx23885-cards.c
+++ b/drivers/media/video/cx23885/cx23885-cards.c
@@ -213,8 +213,8 @@ struct cx23885_board cx23885_boards[] = {
.portc = CX23885_MPEG_DVB,
.tuner_type = TUNER_XC4000,
.tuner_addr = 0x61,
- .radio_type = TUNER_XC4000,
- .radio_addr = 0x61,
+ .radio_type = UNSET,
+ .radio_addr = ADDR_UNSET,
.input = {{
.type = CX23885_VMUX_TELEVISION,
.vmux = CX25840_VIN2_CH1 |
@@ -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 40e68b22015e..6ad227029a0f 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 bcb45be44bb2..6835eb1fc093 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;
@@ -940,6 +943,11 @@ static int dvb_register(struct cx23885_tsport *port)
fe = dvb_attach(xc4000_attach, fe0->dvb.frontend,
&dev->i2c_bus[1].i2c_adap, &cfg);
+ if (!fe) {
+ printk(KERN_ERR "%s/2: xc4000 attach failed\n",
+ dev->name);
+ goto frontend_detach;
+ }
}
break;
case CX23885_BOARD_TBS_6920:
@@ -1043,6 +1051,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 +1140,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 +1206,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 0ff7a9e98f3e..be1e21d8295c 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 e730b9263016..c654bdc7ccb2 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,103 @@ 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;
+
+ 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) {
+ mutex_unlock(&dev->lock);
+ return -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 +1733,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 b49036fe3ffd..f020f0568df4 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 09e99de5fd21..03cfac476b03 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 c20d6dece154..20c7ca3351a8 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 8eb55b7b88cb..1fc2d24f5110 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 6ace60313b49..99988c988095 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 a7fa38f9594e..f617474f9073 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 4d3d0ce40785..12d7300fa1e9 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 60d197f57556..7a9e6470ba22 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 1c1c228352d1..c98ac946b277 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 fc780d0908dc..298a68d98c2f 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 2a724ddfa53f..5a157cf4a95e 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 c0b80068f468..21e7d657f049 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 4d6907cda75b..ffd8bc79c02e 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 2d2d00932823..b9aa801b00a7 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 005f11093642..34b96c7cfd62 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 cd9976408ab3..05247d4c340a 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 5c42abdf422f..3598dc087b08 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 68d1240f493c..04bf6627d362 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 0d719faafd8a..cbd5d119a2c6 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,
@@ -1573,8 +1573,8 @@ static const struct cx88_board cx88_boards[] = {
.name = "Pinnacle Hybrid PCTV",
.tuner_type = TUNER_XC2028,
.tuner_addr = 0x61,
- .radio_type = TUNER_XC2028,
- .radio_addr = 0x61,
+ .radio_type = UNSET,
+ .radio_addr = ADDR_UNSET,
.input = { {
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
@@ -1611,8 +1611,8 @@ static const struct cx88_board cx88_boards[] = {
.name = "Leadtek TV2000 XP Global",
.tuner_type = TUNER_XC2028,
.tuner_addr = 0x61,
- .radio_type = TUNER_XC2028,
- .radio_addr = 0x61,
+ .radio_type = UNSET,
+ .radio_addr = ADDR_UNSET,
.input = { {
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
@@ -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,
@@ -2043,8 +2115,8 @@ static const struct cx88_board cx88_boards[] = {
.name = "Terratec Cinergy HT PCI MKII",
.tuner_type = TUNER_XC2028,
.tuner_addr = 0x61,
- .radio_type = TUNER_XC2028,
- .radio_addr = 0x61,
+ .radio_type = UNSET,
+ .radio_addr = ADDR_UNSET,
.input = { {
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
@@ -2082,9 +2154,9 @@ static const struct cx88_board cx88_boards[] = {
[CX88_BOARD_WINFAST_DTV1800H] = {
.name = "Leadtek WinFast DTV1800 Hybrid",
.tuner_type = TUNER_XC2028,
- .radio_type = TUNER_XC2028,
+ .radio_type = UNSET,
.tuner_addr = 0x61,
- .radio_addr = 0x61,
+ .radio_addr = ADDR_UNSET,
/*
* GPIO setting
*
@@ -2123,9 +2195,9 @@ static const struct cx88_board cx88_boards[] = {
[CX88_BOARD_WINFAST_DTV1800H_XC4000] = {
.name = "Leadtek WinFast DTV1800 H (XC4000)",
.tuner_type = TUNER_XC4000,
- .radio_type = TUNER_XC4000,
+ .radio_type = UNSET,
.tuner_addr = 0x61,
- .radio_addr = 0x61,
+ .radio_addr = ADDR_UNSET,
/*
* GPIO setting
*
@@ -2164,9 +2236,9 @@ static const struct cx88_board cx88_boards[] = {
[CX88_BOARD_WINFAST_DTV2000H_PLUS] = {
.name = "Leadtek WinFast DTV2000 H PLUS",
.tuner_type = TUNER_XC4000,
- .radio_type = TUNER_XC4000,
+ .radio_type = UNSET,
.tuner_addr = 0x61,
- .radio_addr = 0x61,
+ .radio_addr = ADDR_UNSET,
/*
* GPIO
* 2: 1: mute audio
@@ -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 cf3d33ab541b..003937cd72f5 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 a1fe0abb6e43..de0f1af74e41 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 e614201b5ed3..ebf448c48ca3 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 fa8d307e1a3d..c9659def2a78 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 bd443ee76fff..f83baf3a52b0 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 8051c2956478..9303fe553b07 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 29c29c668596..1e63852374be 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 d773d30de221..c4a82a1a8a97 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 8588a86d9b45..1f3b1c729252 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 ceccf4302518..d6488b79ae3b 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 03a3e5c65ee7..00e80f59d5d5 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 5b38fc93ff28..20cf271a774b 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 49e4deb50043..6504e40a31dd 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 cff0768afbf5..e2a7b77c39c7 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 93807dcf944e..4561cd89938d 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 804a4ab47ac6..0aacc96f9a23 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 cef7a2d409cb..9449423098e0 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 679da4804281..2630b265b0e8 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 66f792361b97..2f6268505726 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 9b4557a2f6d0..613300b51a9e 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 2a2cb7ed0014..22e252bcc41e 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 40f214ab924f..5539f09440ac 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 27cb197d0bd6..27e3e0c0b219 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 103af3fe5aa0..dfe268bfa4f8 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 f345f494d0f3..79ebe46e1ad7 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 636627b57dc9..9769f17915c0 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 a8f54c20e585..c84e26006fc3 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 2ca10dfec91f..ca5a2b139d0b 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 e444f16e1497..589009f4496f 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 000000000000..53f58ef367cf
--- /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 b1da7f4096c8..f0c0d74dfe92 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 9fe3816b2aa0..0c4493675438 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 b1f0c492036a..8c672b5c8c6a 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 2efd607987ec..2b6a13b508f7 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 da9a129b739d..f7aa5bf68983 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 338359596398..81a2bcb88fe3 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 8cc7a3f6da72..8e0035e731c7 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 80a63a236e24..79952247b534 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 5c2ea05c46b4..b0231465afae 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 d4bec9321771..7167cac7359c 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 08b8ce1dee18..739e8a2a2d30 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 f30060d50633..fbfa02affa13 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 ece8b1e82a13..3844c49f269c 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 2811195258c4..9db2b34d172c 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 1494e1829d36..bb70092c2229 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 33cabc342dcf..9e198b45c3c8 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 ddb392dc4f2d..6a1148d7fe92 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 afa3186b8038..0c9e6ddabd2c 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 259a0c73c664..4a5f209ce719 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 0ab425fbea9a..91d99b4cc57b 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 ea44deb66af4..9b9f85a8e60e 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 b2695b1dc603..444d3c5b9079 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 d12ea1518ace..911152e169d6 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 fbb6ed25ec31..ecada178bceb 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 0202fead6b97..b9e15bb0328b 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 3f1a5b1beeba..e5eb56a5b618 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 3ab875d036e1..a7c41d32f414 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 41108a9a195e..3949b7dc2368 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[] = "--";
@@ -731,9 +731,6 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv)
init_kthread_work(&itv->irq_work, ivtv_irq_work_handler);
- /* start counting open_id at 1 */
- itv->open_id = 1;
-
/* Initial settings */
itv->cxhdl.port = CX2341X_PORT_MEMORY;
itv->cxhdl.capabilities = CX2341X_CAP_HAS_SLICED_VBI;
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h
index 8f9cc17b518e..06f3d78389bf 100644
--- a/drivers/media/video/ivtv/ivtv-driver.h
+++ b/drivers/media/video/ivtv/ivtv-driver.h
@@ -332,7 +332,7 @@ struct ivtv_stream {
const char *name; /* name of the stream */
int type; /* stream type */
- u32 id;
+ struct v4l2_fh *fh; /* pointer to the streaming filehandle */
spinlock_t qlock; /* locks access to the queues */
unsigned long s_flags; /* status flags, see above */
int dma; /* can be PCI_DMA_TODEVICE, PCI_DMA_FROMDEVICE or PCI_DMA_NONE */
@@ -379,7 +379,6 @@ struct ivtv_stream {
struct ivtv_open_id {
struct v4l2_fh fh;
- u32 open_id; /* unique ID for this file descriptor */
int type; /* stream type */
int yuv_frames; /* 1: started OUT_UDMA_YUV output mode */
struct ivtv *itv;
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c
index 38f052257f46..2cd6c89b7d91 100644
--- a/drivers/media/video/ivtv/ivtv-fileops.c
+++ b/drivers/media/video/ivtv/ivtv-fileops.c
@@ -50,16 +50,16 @@ static int ivtv_claim_stream(struct ivtv_open_id *id, int type)
if (test_and_set_bit(IVTV_F_S_CLAIMED, &s->s_flags)) {
/* someone already claimed this stream */
- if (s->id == id->open_id) {
+ if (s->fh == &id->fh) {
/* yes, this file descriptor did. So that's OK. */
return 0;
}
- if (s->id == -1 && (type == IVTV_DEC_STREAM_TYPE_VBI ||
+ if (s->fh == NULL && (type == IVTV_DEC_STREAM_TYPE_VBI ||
type == IVTV_ENC_STREAM_TYPE_VBI)) {
/* VBI is handled already internally, now also assign
the file descriptor to this stream for external
reading of the stream. */
- s->id = id->open_id;
+ s->fh = &id->fh;
IVTV_DEBUG_INFO("Start Read VBI\n");
return 0;
}
@@ -67,7 +67,7 @@ static int ivtv_claim_stream(struct ivtv_open_id *id, int type)
IVTV_DEBUG_INFO("Stream %d is busy\n", type);
return -EBUSY;
}
- s->id = id->open_id;
+ s->fh = &id->fh;
if (type == IVTV_DEC_STREAM_TYPE_VBI) {
/* Enable reinsertion interrupt */
ivtv_clear_irq_mask(itv, IVTV_IRQ_DEC_VBI_RE_INSERT);
@@ -104,7 +104,7 @@ void ivtv_release_stream(struct ivtv_stream *s)
struct ivtv *itv = s->itv;
struct ivtv_stream *s_vbi;
- s->id = -1;
+ s->fh = NULL;
if ((s->type == IVTV_DEC_STREAM_TYPE_VBI || s->type == IVTV_ENC_STREAM_TYPE_VBI) &&
test_bit(IVTV_F_S_INTERNAL_USE, &s->s_flags)) {
/* this stream is still in use internally */
@@ -136,7 +136,7 @@ void ivtv_release_stream(struct ivtv_stream *s)
/* was already cleared */
return;
}
- if (s_vbi->id != -1) {
+ if (s_vbi->fh) {
/* VBI stream still claimed by a file descriptor */
return;
}
@@ -268,11 +268,13 @@ static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block,
}
/* wait for more data to arrive */
+ mutex_unlock(&itv->serialize_lock);
prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
/* New buffers might have become available before we were added to the waitqueue */
if (!s->q_full.buffers)
schedule();
finish_wait(&s->waitq, &wait);
+ mutex_lock(&itv->serialize_lock);
if (signal_pending(current)) {
/* return if a signal was received */
IVTV_DEBUG_INFO("User stopped %s\n", s->name);
@@ -357,7 +359,7 @@ static ssize_t ivtv_read(struct ivtv_stream *s, char __user *ubuf, size_t tot_co
size_t tot_written = 0;
int single_frame = 0;
- if (atomic_read(&itv->capturing) == 0 && s->id == -1) {
+ if (atomic_read(&itv->capturing) == 0 && s->fh == NULL) {
/* shouldn't happen */
IVTV_DEBUG_WARN("Stream %s not initialized before read\n", s->name);
return -EIO;
@@ -507,9 +509,7 @@ ssize_t ivtv_v4l2_read(struct file * filp, char __user *buf, size_t count, loff_
IVTV_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name);
- mutex_lock(&itv->serialize_lock);
rc = ivtv_start_capture(id);
- mutex_unlock(&itv->serialize_lock);
if (rc)
return rc;
return ivtv_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK);
@@ -584,9 +584,7 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c
set_bit(IVTV_F_S_APPL_IO, &s->s_flags);
/* Start decoder (returns 0 if already started) */
- mutex_lock(&itv->serialize_lock);
rc = ivtv_start_decoding(id, itv->speed);
- mutex_unlock(&itv->serialize_lock);
if (rc) {
IVTV_DEBUG_WARN("Failed start decode stream %s\n", s->name);
@@ -627,11 +625,13 @@ retry:
break;
if (filp->f_flags & O_NONBLOCK)
return -EAGAIN;
+ mutex_unlock(&itv->serialize_lock);
prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
/* New buffers might have become free before we were added to the waitqueue */
if (!s->q_free.buffers)
schedule();
finish_wait(&s->waitq, &wait);
+ mutex_lock(&itv->serialize_lock);
if (signal_pending(current)) {
IVTV_DEBUG_INFO("User stopped %s\n", s->name);
return -EINTR;
@@ -686,12 +686,14 @@ retry:
if (mode == OUT_YUV)
ivtv_yuv_setup_stream_frame(itv);
+ mutex_unlock(&itv->serialize_lock);
prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
while (!(got_sig = signal_pending(current)) &&
test_bit(IVTV_F_S_DMA_PENDING, &s->s_flags)) {
schedule();
}
finish_wait(&itv->dma_waitq, &wait);
+ mutex_lock(&itv->serialize_lock);
if (got_sig) {
IVTV_DEBUG_INFO("User interrupted %s\n", s->name);
return -EINTR;
@@ -756,9 +758,7 @@ unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait)
if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
int rc;
- mutex_lock(&itv->serialize_lock);
rc = ivtv_start_capture(id);
- mutex_unlock(&itv->serialize_lock);
if (rc) {
IVTV_DEBUG_INFO("Could not start capture for %s (%d)\n",
s->name, rc);
@@ -808,7 +808,7 @@ void ivtv_stop_capture(struct ivtv_open_id *id, int gop_end)
id->type == IVTV_ENC_STREAM_TYPE_VBI) &&
test_bit(IVTV_F_S_INTERNAL_USE, &s->s_flags)) {
/* Also used internally, don't stop capturing */
- s->id = -1;
+ s->fh = NULL;
}
else {
ivtv_stop_v4l2_encode_stream(s, gop_end);
@@ -861,20 +861,9 @@ int ivtv_v4l2_close(struct file *filp)
IVTV_DEBUG_FILE("close %s\n", s->name);
- v4l2_fh_del(fh);
- v4l2_fh_exit(fh);
-
- /* Easy case first: this stream was never claimed by us */
- if (s->id != id->open_id) {
- kfree(id);
- return 0;
- }
-
- /* 'Unclaim' this stream */
-
/* Stop radio */
- mutex_lock(&itv->serialize_lock);
- if (id->type == IVTV_ENC_STREAM_TYPE_RAD) {
+ if (id->type == IVTV_ENC_STREAM_TYPE_RAD &&
+ v4l2_fh_is_singular_file(filp)) {
/* Closing radio device, return to TV mode */
ivtv_mute(itv);
/* Mark that the radio is no longer in use */
@@ -890,13 +879,25 @@ int ivtv_v4l2_close(struct file *filp)
if (atomic_read(&itv->capturing) > 0) {
/* Undo video mute */
ivtv_vapi(itv, CX2341X_ENC_MUTE_VIDEO, 1,
- v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute) |
- (v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute_yuv) << 8));
+ v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute) |
+ (v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute_yuv) << 8));
}
/* Done! Unmute and continue. */
ivtv_unmute(itv);
- ivtv_release_stream(s);
- } else if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) {
+ }
+
+ v4l2_fh_del(fh);
+ v4l2_fh_exit(fh);
+
+ /* Easy case first: this stream was never claimed by us */
+ if (s->fh != &id->fh) {
+ kfree(id);
+ return 0;
+ }
+
+ /* 'Unclaim' this stream */
+
+ if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) {
struct ivtv_stream *s_vout = &itv->streams[IVTV_DEC_STREAM_TYPE_VOUT];
ivtv_stop_decoding(id, VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0);
@@ -911,21 +912,25 @@ int ivtv_v4l2_close(struct file *filp)
ivtv_stop_capture(id, 0);
}
kfree(id);
- mutex_unlock(&itv->serialize_lock);
return 0;
}
-static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp)
+int ivtv_v4l2_open(struct file *filp)
{
-#ifdef CONFIG_VIDEO_ADV_DEBUG
struct video_device *vdev = video_devdata(filp);
-#endif
+ struct ivtv_stream *s = video_get_drvdata(vdev);
struct ivtv *itv = s->itv;
struct ivtv_open_id *item;
int res = 0;
IVTV_DEBUG_FILE("open %s\n", s->name);
+ if (ivtv_init_on_first_open(itv)) {
+ IVTV_ERR("Failed to initialize on device %s\n",
+ video_device_node_name(vdev));
+ return -ENXIO;
+ }
+
#ifdef CONFIG_VIDEO_ADV_DEBUG
/* Unless ivtv_fw_debug is set, error out if firmware dead. */
if (ivtv_fw_debug) {
@@ -966,31 +971,19 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp)
return -ENOMEM;
}
v4l2_fh_init(&item->fh, s->vdev);
- if (res < 0) {
- v4l2_fh_exit(&item->fh);
- kfree(item);
- return res;
- }
item->itv = itv;
item->type = s->type;
- item->open_id = itv->open_id++;
filp->private_data = &item->fh;
+ v4l2_fh_add(&item->fh);
- if (item->type == IVTV_ENC_STREAM_TYPE_RAD) {
- /* Try to claim this stream */
- if (ivtv_claim_stream(item, item->type)) {
- /* No, it's already in use */
- v4l2_fh_exit(&item->fh);
- kfree(item);
- return -EBUSY;
- }
-
+ if (item->type == IVTV_ENC_STREAM_TYPE_RAD &&
+ v4l2_fh_is_singular_file(filp)) {
if (!test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) {
if (atomic_read(&itv->capturing) > 0) {
/* switching to radio while capture is
in progress is not polite */
- ivtv_release_stream(s);
+ v4l2_fh_del(&item->fh);
v4l2_fh_exit(&item->fh);
kfree(item);
return -EBUSY;
@@ -1022,32 +1015,9 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp)
1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31);
itv->yuv_info.stream_size = 0;
}
- v4l2_fh_add(&item->fh);
return 0;
}
-int ivtv_v4l2_open(struct file *filp)
-{
- int res;
- struct ivtv *itv = NULL;
- struct ivtv_stream *s = NULL;
- struct video_device *vdev = video_devdata(filp);
-
- s = video_get_drvdata(vdev);
- itv = s->itv;
-
- mutex_lock(&itv->serialize_lock);
- if (ivtv_init_on_first_open(itv)) {
- IVTV_ERR("Failed to initialize on device %s\n",
- video_device_node_name(vdev));
- mutex_unlock(&itv->serialize_lock);
- return -ENXIO;
- }
- res = ivtv_serialized_open(s, filp);
- mutex_unlock(&itv->serialize_lock);
- return res;
-}
-
void ivtv_mute(struct ivtv *itv)
{
if (atomic_read(&itv->capturing))
diff --git a/drivers/media/video/ivtv/ivtv-i2c.h b/drivers/media/video/ivtv/ivtv-i2c.h
index 9332920ca4ff..7b9ec1cfeb80 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/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c
index ecafa697326e..c4bc48143098 100644
--- a/drivers/media/video/ivtv/ivtv-ioctl.c
+++ b/drivers/media/video/ivtv/ivtv-ioctl.c
@@ -179,6 +179,7 @@ int ivtv_set_speed(struct ivtv *itv, int speed)
ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, 0);
/* Wait for any DMA to finish */
+ mutex_unlock(&itv->serialize_lock);
prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
while (test_bit(IVTV_F_I_DMA, &itv->i_flags)) {
got_sig = signal_pending(current);
@@ -188,6 +189,7 @@ int ivtv_set_speed(struct ivtv *itv, int speed)
schedule();
}
finish_wait(&itv->dma_waitq, &wait);
+ mutex_lock(&itv->serialize_lock);
if (got_sig)
return -EINTR;
@@ -1107,6 +1109,7 @@ void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std)
* happens within the first 100 lines of the top field.
* Make 4 attempts to sync to the decoder before giving up.
*/
+ mutex_unlock(&itv->serialize_lock);
for (f = 0; f < 4; f++) {
prepare_to_wait(&itv->vsync_waitq, &wait,
TASK_UNINTERRUPTIBLE);
@@ -1115,6 +1118,7 @@ void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std)
schedule_timeout(msecs_to_jiffies(25));
}
finish_wait(&itv->vsync_waitq, &wait);
+ mutex_lock(&itv->serialize_lock);
if (f == 4)
IVTV_WARN("Mode change failed to sync to decoder\n");
@@ -1842,8 +1846,7 @@ static long ivtv_default(struct file *file, void *fh, bool valid_prio,
return 0;
}
-static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp,
- unsigned int cmd, unsigned long arg)
+long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct video_device *vfd = video_devdata(filp);
long ret;
@@ -1855,21 +1858,6 @@ static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp,
return ret;
}
-long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
- struct ivtv_open_id *id = fh2id(filp->private_data);
- struct ivtv *itv = id->itv;
- long res;
-
- /* DQEVENT can block, so this should not run with the serialize lock */
- if (cmd == VIDIOC_DQEVENT)
- return ivtv_serialized_ioctl(itv, filp, cmd, arg);
- mutex_lock(&itv->serialize_lock);
- res = ivtv_serialized_ioctl(itv, filp, cmd, arg);
- mutex_unlock(&itv->serialize_lock);
- return res;
-}
-
static const struct v4l2_ioctl_ops ivtv_ioctl_ops = {
.vidioc_querycap = ivtv_querycap,
.vidioc_s_audio = ivtv_s_audio,
diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c
index 9c29e964d400..1b3b9578bf47 100644
--- a/drivers/media/video/ivtv/ivtv-irq.c
+++ b/drivers/media/video/ivtv/ivtv-irq.c
@@ -288,13 +288,13 @@ static void dma_post(struct ivtv_stream *s)
ivtv_process_vbi_data(itv, buf, 0, s->type);
s->q_dma.bytesused += buf->bytesused;
}
- if (s->id == -1) {
+ if (s->fh == NULL) {
ivtv_queue_move(s, &s->q_dma, NULL, &s->q_free, 0);
return;
}
}
ivtv_queue_move(s, &s->q_dma, NULL, &s->q_full, s->q_dma.bytesused);
- if (s->id != -1)
+ if (s->fh)
wake_up(&s->waitq);
}
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c
index e7794dc1330e..c6e28b4ebbed 100644
--- a/drivers/media/video/ivtv/ivtv-streams.c
+++ b/drivers/media/video/ivtv/ivtv-streams.c
@@ -159,7 +159,6 @@ static void ivtv_stream_init(struct ivtv *itv, int type)
s->buffers = (itv->options.kilobytes[type] * 1024 + s->buf_size - 1) / s->buf_size;
spin_lock_init(&s->qlock);
init_waitqueue_head(&s->waitq);
- s->id = -1;
s->sg_handle = IVTV_DMA_UNMAPPED;
ivtv_queue_init(&s->q_free);
ivtv_queue_init(&s->q_full);
@@ -214,6 +213,7 @@ static int ivtv_prep_dev(struct ivtv *itv, int type)
s->vdev->fops = ivtv_stream_info[type].fops;
s->vdev->release = video_device_release;
s->vdev->tvnorms = V4L2_STD_ALL;
+ s->vdev->lock = &itv->serialize_lock;
set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev->flags);
ivtv_set_funcs(s->vdev);
return 0;
diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c
index dcbab6ad4c26..2ad65eb29832 100644
--- a/drivers/media/video/ivtv/ivtv-yuv.c
+++ b/drivers/media/video/ivtv/ivtv-yuv.c
@@ -1149,23 +1149,37 @@ int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src)
{
struct yuv_playback_info *yi = &itv->yuv_info;
struct ivtv_dma_frame dma_args;
+ int res;
ivtv_yuv_setup_stream_frame(itv);
/* We only need to supply source addresses for this */
dma_args.y_source = src;
dma_args.uv_source = src + 720 * ((yi->v4l2_src_h + 31) & ~31);
- return ivtv_yuv_udma_frame(itv, &dma_args);
+ /* Wait for frame DMA. Note that serialize_lock is locked,
+ so to allow other processes to access the driver while
+ we are waiting unlock first and later lock again. */
+ mutex_unlock(&itv->serialize_lock);
+ res = ivtv_yuv_udma_frame(itv, &dma_args);
+ mutex_lock(&itv->serialize_lock);
+ return res;
}
/* IVTV_IOC_DMA_FRAME ioctl handler */
int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
{
-/* IVTV_DEBUG_INFO("yuv_prep_frame\n"); */
+ int res;
+/* IVTV_DEBUG_INFO("yuv_prep_frame\n"); */
ivtv_yuv_next_free(itv);
ivtv_yuv_setup_frame(itv, args);
- return ivtv_yuv_udma_frame(itv, args);
+ /* Wait for frame DMA. Note that serialize_lock is locked,
+ so to allow other processes to access the driver while
+ we are waiting unlock first and later lock again. */
+ mutex_unlock(&itv->serialize_lock);
+ res = ivtv_yuv_udma_frame(itv, args);
+ mutex_lock(&itv->serialize_lock);
+ return res;
}
void ivtv_yuv_close(struct ivtv *itv)
@@ -1174,7 +1188,9 @@ void ivtv_yuv_close(struct ivtv *itv)
int h_filter, v_filter_1, v_filter_2;
IVTV_DEBUG_YUV("ivtv_yuv_close\n");
+ mutex_unlock(&itv->serialize_lock);
ivtv_waitq(&itv->vsync_waitq);
+ mutex_lock(&itv->serialize_lock);
yi->running = 0;
atomic_set(&yi->next_dma_frame, -1);
diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c
index 6b7c9c823330..d0fbfcf7133d 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 82c8817bd32d..4b021e1ee5f2 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 3248ac805711..ba25e8e2ba4c 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 e0f09e531800..93d768db9f33 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 c755bd6edfe9..ae4aced0f9b2 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 80ec64d2d6d8..37d20e73908a 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 fb0b124b35f3..0d64e2d7474a 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 d0f538857285..d7cd0f633f63 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 831e8db4368c..fbe5e0715f93 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 e2b1029b16cd..097c9d3d04a8 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 398f96ffd35e..bee65bff46e8 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 73c068993f05..93c3ec7426e8 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 08074b8a2736..cd81d04a529e 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 0e78477452ff..84add1aef139 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 690ee0d42eeb..944940758fa3 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 f080c162123f..d90b982cc218 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 18e94c7d2be8..055d11ddb038 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 a803d9ea8fd6..04aab0c538aa 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 f96f92f00f92..74522773e934 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 ee0d0b39cd17..1fb7d5bd5ec2 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);
@@ -1041,7 +1042,8 @@ static int vidioc_querycap(struct file *file, void *fh,
strlcpy(cap->driver, VOUT_NAME, sizeof(cap->driver));
strlcpy(cap->card, vout->vfd->name, sizeof(cap->card));
cap->bus_info[0] = '\0';
- cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT;
+ cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT |
+ V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
return 0;
}
@@ -1668,7 +1670,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 +1688,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 +1727,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 */
@@ -1823,7 +1826,9 @@ static int vidioc_g_fbuf(struct file *file, void *fh,
ovid = &vout->vid_info;
ovl = ovid->overlays[0];
- a->flags = 0x0;
+ /* The video overlay must stay within the framebuffer and can't be
+ positioned independently. */
+ a->flags = V4L2_FBUF_FLAG_OVERLAY;
a->capability = V4L2_FBUF_CAP_LOCAL_ALPHA | V4L2_FBUF_CAP_CHROMAKEY
| V4L2_FBUF_CAP_SRC_CHROMAKEY;
diff --git a/drivers/media/video/omap/omap_vout_vrfb.c b/drivers/media/video/omap/omap_vout_vrfb.c
index ebebcac49225..4be26abf6cea 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 d793501cafcc..27a95d23b913 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 6a6cf388bae4..c20f5ecd6790 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 45522e603185..7d3864144368 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 d4c48ef227fb..12d5f923e1d0 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 d341ba12593f..a74a79701d34 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 483a19cac1ad..6d0264bab75b 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 904ca8c8b17f..70ddbf35b223 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 6674e9de2cd7..76d65f4576ef 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 0c5f1cb9d99d..fcb5168996a7 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 456fb7fb8a0f..885ad79a7678 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 ccb876fe023f..6d0fb2c8c26d 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 f54e775c2df4..09686607973c 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 50e593bfcfaf..6958a9e3dc22 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 76abc2e42126..70c1c0e1bbdf 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 bd3aebafafa0..b02070057724 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 08cbfa144e6e..d91bdb919be0 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 8aa058531280..6a564964853a 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 122b45760f0d..ebc2c7e39233 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 3977addf3ba8..1f506fde97d0 100644
--- a/drivers/media/video/pwc/pwc-ctrl.c
+++ b/drivers/media/video/pwc/pwc-ctrl.c
@@ -102,52 +102,18 @@ 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,
- u8 request, u16 value, int index, void *buf, int buflen)
-{
- int rc;
- void *kbuf = NULL;
-
- if (buflen) {
- kbuf = kmalloc(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),
- request,
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- value,
- index,
- kbuf, buflen, USB_CTRL_SET_TIMEOUT);
-
- kfree(kbuf);
- return rc;
-}
-
static int recv_control_msg(struct pwc_device *pdev,
- u8 request, u16 value, void *buf, int buflen)
+ u8 request, u16 value, int recv_count)
{
int rc;
- void *kbuf = kmalloc(buflen, GFP_KERNEL); /* not allowed on stack */
-
- if (kbuf == NULL)
- return -ENOMEM;
rc = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
request,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- value,
- pdev->vcinterface,
- kbuf, buflen, USB_CTRL_GET_TIMEOUT);
- memcpy(buf, kbuf, buflen);
- kfree(kbuf);
-
+ value, pdev->vcinterface,
+ pdev->ctrl_buf, recv_count, USB_CTRL_GET_TIMEOUT);
if (rc < 0)
PWC_ERROR("recv_control_msg error %d req %02x val %04x\n",
rc, request, value);
@@ -155,26 +121,39 @@ static int recv_control_msg(struct pwc_device *pdev,
}
static inline int send_video_command(struct pwc_device *pdev,
- int index, void *buf, int buflen)
+ int index, const unsigned char *buf, int buflen)
{
- return _send_control_msg(pdev,
- SET_EP_STREAM_CTL,
- VIDEO_OUTPUT_CONTROL_FORMATTER,
- index,
- buf, buflen);
+ int rc;
+
+ memcpy(pdev->ctrl_buf, buf, buflen);
+
+ rc = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+ SET_EP_STREAM_CTL,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ VIDEO_OUTPUT_CONTROL_FORMATTER, index,
+ pdev->ctrl_buf, buflen, USB_CTRL_SET_TIMEOUT);
+ if (rc >= 0)
+ memcpy(pdev->cmd_buf, buf, buflen);
+ else
+ PWC_ERROR("send_video_command error %d\n", rc);
+
+ return rc;
}
int send_control_msg(struct pwc_device *pdev,
u8 request, u16 value, void *buf, int buflen)
{
- return _send_control_msg(pdev,
- request, value, pdev->vcinterface, buf, buflen);
+ return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+ request,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ value, pdev->vcinterface,
+ buf, buflen, USB_CTRL_SET_TIMEOUT);
}
-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 pixfmt,
+ int frames, int *compression, int send_to_cam)
{
- unsigned char buf[3];
- int ret, fps;
+ int fps, ret = 0;
struct Nala_table_entry *pEntry;
int frames2frames[31] =
{ /* closest match of framerate */
@@ -196,35 +175,34 @@ static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
7 /* 30 */
};
- if (size < 0 || size > PSZ_CIF || frames < 4 || frames > 25)
+ if (size < 0 || size > PSZ_CIF)
return -EINVAL;
+ if (frames < 4)
+ frames = 4;
+ else if (frames > 25)
+ frames = 25;
frames = frames2frames[frames];
fps = frames2table[frames];
pEntry = &Nala_table[size][fps];
if (pEntry->alternate == 0)
return -EINVAL;
- memcpy(buf, pEntry->mode, 3);
- ret = send_video_command(pdev, pdev->vendpoint, buf, 3);
- if (ret < 0) {
- PWC_DEBUG_MODULE("Failed to send video command... %d\n", ret);
+ if (send_to_cam)
+ ret = send_video_command(pdev, pdev->vendpoint,
+ pEntry->mode, 3);
+ if (ret < 0)
return ret;
- }
- if (pEntry->compressed && pdev->pixfmt == V4L2_PIX_FMT_YUV420) {
- ret = pwc_dec1_init(pdev, pdev->type, pdev->release, buf);
- if (ret < 0)
- return ret;
- }
- pdev->cmd_len = 3;
- memcpy(pdev->cmd_buf, buf, 3);
+ if (pEntry->compressed && pixfmt == V4L2_PIX_FMT_YUV420)
+ pwc_dec1_init(pdev, pEntry->mode);
/* Set various parameters */
+ pdev->pixfmt = pixfmt;
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,183 +215,142 @@ 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 pixfmt,
+ int frames, int *compression, int send_to_cam)
{
- unsigned char buf[13];
const struct Timon_table_entry *pChoose;
- int ret, fps;
+ int fps, ret = 0;
- if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3)
- return -EINVAL;
- if (size == PSZ_VGA && frames > 15)
+ if (size >= PSZ_MAX || *compression < 0 || *compression > 3)
return -EINVAL;
+ if (frames < 5)
+ frames = 5;
+ else if (size == PSZ_VGA && frames > 15)
+ frames = 15;
+ else if (frames > 30)
+ frames = 30;
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 (send_to_cam)
+ ret = send_video_command(pdev, pdev->vendpoint,
+ pChoose->mode, 13);
if (ret < 0)
return ret;
- if (pChoose->bandlength > 0 && pdev->pixfmt == V4L2_PIX_FMT_YUV420) {
- ret = pwc_dec23_init(pdev, pdev->type, buf);
- if (ret < 0)
- return ret;
- }
-
- pdev->cmd_len = 13;
- memcpy(pdev->cmd_buf, buf, 13);
+ if (pChoose->bandlength > 0 && pixfmt == V4L2_PIX_FMT_YUV420)
+ pwc_dec23_init(pdev, pChoose->mode);
/* Set various parameters */
- pdev->vframes = frames;
- pdev->vsize = size;
- pdev->vsnapshot = snapshot;
+ pdev->pixfmt = pixfmt;
+ pdev->vframes = (fps + 1) * 5;
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 pixfmt,
+ int frames, int *compression, int send_to_cam)
{
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}};
+ int fps, ret = 0;
- if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3)
- return -EINVAL;
- if (size == PSZ_VGA && frames > 15)
+ if (size >= PSZ_MAX || *compression < 0 || *compression > 3)
return -EINVAL;
+ if (frames < 5)
+ frames = 5;
+ else if (size == PSZ_VGA && frames > 15)
+ frames = 15;
+ else if (frames > 30)
+ frames = 30;
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. */
- PWC_TRACE("Using alternate setting %d.\n", pChoose->alternate);
-
- /* 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);
+ if (send_to_cam)
+ ret = send_video_command(pdev, 4, pChoose->mode, 12);
if (ret < 0)
return ret;
- if (pChoose->bandlength > 0 && pdev->pixfmt == V4L2_PIX_FMT_YUV420) {
- ret = pwc_dec23_init(pdev, pdev->type, buf);
- if (ret < 0)
- return ret;
- }
+ if (pChoose->bandlength > 0 && pixfmt == V4L2_PIX_FMT_YUV420)
+ pwc_dec23_init(pdev, pChoose->mode);
- pdev->cmd_len = 12;
- memcpy(pdev->cmd_buf, buf, 12);
/* All set and go */
- pdev->vframes = frames;
- pdev->vsize = size;
- pdev->vsnapshot = snapshot;
+ pdev->pixfmt = pixfmt;
+ pdev->vframes = (fps + 1) * 5;
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 pixfmt, int frames, int *compression, int send_to_cam)
{
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;
- }
+ PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, pixfmt %08x).\n",
+ width, height, frames, pixfmt);
+ 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, pixfmt, frames,
+ compression, send_to_cam);
} else if (DEVICE_USE_CODEC3(pdev->type)) {
- ret = set_video_mode_Kiara(pdev, size, frames, compression, snapshot);
-
+ ret = set_video_mode_Kiara(pdev, size, pixfmt, frames,
+ compression, send_to_cam);
} else {
- ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot);
+ ret = set_video_mode_Timon(pdev, size, pixfmt, frames,
+ compression, send_to_cam);
}
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,44 +407,15 @@ 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;
- u8 buf;
- ret = recv_control_msg(pdev, request, value, &buf, sizeof(buf));
+ ret = recv_control_msg(pdev, request, value, 1);
if (ret < 0)
return ret;
- *data = buf;
+ *data = pdev->ctrl_buf[0];
return 0;
}
@@ -515,7 +423,8 @@ int pwc_set_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, u8 data)
{
int ret;
- ret = send_control_msg(pdev, request, value, &data, sizeof(data));
+ pdev->ctrl_buf[0] = data;
+ ret = send_control_msg(pdev, request, value, pdev->ctrl_buf, 1);
if (ret < 0)
return ret;
@@ -525,37 +434,34 @@ int pwc_set_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, u8 data)
int pwc_get_s8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
{
int ret;
- s8 buf;
- ret = recv_control_msg(pdev, request, value, &buf, sizeof(buf));
+ ret = recv_control_msg(pdev, request, value, 1);
if (ret < 0)
return ret;
- *data = buf;
+ *data = ((s8 *)pdev->ctrl_buf)[0];
return 0;
}
int pwc_get_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
{
int ret;
- u8 buf[2];
- ret = recv_control_msg(pdev, request, value, buf, sizeof(buf));
+ ret = recv_control_msg(pdev, request, value, 2);
if (ret < 0)
return ret;
- *data = (buf[1] << 8) | buf[0];
+ *data = (pdev->ctrl_buf[1] << 8) | pdev->ctrl_buf[0];
return 0;
}
int pwc_set_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, u16 data)
{
int ret;
- u8 buf[2];
- buf[0] = data & 0xff;
- buf[1] = data >> 8;
- ret = send_control_msg(pdev, request, value, buf, sizeof(buf));
+ pdev->ctrl_buf[0] = data & 0xff;
+ pdev->ctrl_buf[1] = data >> 8;
+ ret = send_control_msg(pdev, request, value, pdev->ctrl_buf, 2);
if (ret < 0)
return ret;
@@ -576,7 +482,6 @@ int pwc_button_ctrl(struct pwc_device *pdev, u16 value)
/* POWER */
void pwc_camera_power(struct pwc_device *pdev, int power)
{
- char buf;
int r;
if (!pdev->power_save)
@@ -586,69 +491,18 @@ void pwc_camera_power(struct pwc_device *pdev, int power)
return; /* Not supported by Nala or Timon < release 6 */
if (power)
- buf = 0x00; /* active */
+ pdev->ctrl_buf[0] = 0x00; /* active */
else
- buf = 0xFF; /* power save */
- r = send_control_msg(pdev,
- SET_STATUS_CTL, SET_POWER_SAVE_MODE_FORMATTER,
- &buf, sizeof(buf));
-
+ pdev->ctrl_buf[0] = 0xFF; /* power save */
+ r = send_control_msg(pdev, SET_STATUS_CTL,
+ SET_POWER_SAVE_MODE_FORMATTER, pdev->ctrl_buf, 1);
if (r < 0)
PWC_ERROR("Failed to power %s camera (%d)\n",
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];
int r;
if (pdev->type < 730)
@@ -664,123 +518,20 @@ int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
if (off_value > 0xff)
off_value = 0xff;
- buf[0] = on_value;
- buf[1] = off_value;
+ pdev->ctrl_buf[0] = on_value;
+ pdev->ctrl_buf[1] = off_value;
r = send_control_msg(pdev,
- SET_STATUS_CTL, LED_FORMATTER, &buf, sizeof(buf));
+ SET_STATUS_CTL, LED_FORMATTER, pdev->ctrl_buf, 2);
if (r < 0)
PWC_ERROR("Failed to set LED on/off time (%d)\n", r);
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)
{
- unsigned char buf;
int ret = -1, request;
if (pdev->type < 675)
@@ -790,431 +541,13 @@ int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
else
request = SENSOR_TYPE_FORMATTER2;
- ret = recv_control_msg(pdev,
- GET_STATUS_CTL, request, &buf, sizeof(buf));
+ ret = recv_control_msg(pdev, GET_STATUS_CTL, request, 1);
if (ret < 0)
return ret;
if (pdev->type < 675)
- *sensor = buf | 0x100;
+ *sensor = pdev->ctrl_buf[0] | 0x100;
else
- *sensor = buf;
+ *sensor = pdev->ctrl_buf[0];
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-dec1.c b/drivers/media/video/pwc/pwc-dec1.c
index be0e02cb487f..e899036aadf4 100644
--- a/drivers/media/video/pwc/pwc-dec1.c
+++ b/drivers/media/video/pwc/pwc-dec1.c
@@ -22,19 +22,11 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "pwc-dec1.h"
+#include "pwc.h"
-int pwc_dec1_init(struct pwc_device *pwc, int type, int release, void *buffer)
+void pwc_dec1_init(struct pwc_device *pdev, const unsigned char *cmd)
{
- struct pwc_dec1_private *pdec;
+ struct pwc_dec1_private *pdec = &pdev->dec1;
- if (pwc->decompress_data == NULL) {
- pdec = kmalloc(sizeof(struct pwc_dec1_private), GFP_KERNEL);
- if (pdec == NULL)
- return -ENOMEM;
- pwc->decompress_data = pdec;
- }
- pdec = pwc->decompress_data;
-
- return 0;
+ pdec->version = pdev->release;
}
diff --git a/drivers/media/video/pwc/pwc-dec1.h b/drivers/media/video/pwc/pwc-dec1.h
index a57d8601080b..c565ef8f52fb 100644
--- a/drivers/media/video/pwc/pwc-dec1.h
+++ b/drivers/media/video/pwc/pwc-dec1.h
@@ -25,13 +25,15 @@
#ifndef PWC_DEC1_H
#define PWC_DEC1_H
-#include "pwc.h"
+#include <linux/mutex.h>
+
+struct pwc_device;
struct pwc_dec1_private
{
int version;
};
-int pwc_dec1_init(struct pwc_device *pwc, int type, int release, void *buffer);
+void pwc_dec1_init(struct pwc_device *pdev, const unsigned char *cmd);
#endif
diff --git a/drivers/media/video/pwc/pwc-dec23.c b/drivers/media/video/pwc/pwc-dec23.c
index 06a4e877ba40..3792fedff951 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] = {
@@ -302,20 +294,17 @@ static unsigned char pwc_crop_table[256 + 2*MAX_OUTER_CROP_VALUE];
/* If the type or the command change, we rebuild the lookup table */
-int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd)
+void pwc_dec23_init(struct pwc_device *pdev, const unsigned char *cmd)
{
int flags, version, shift, i;
- struct pwc_dec23_private *pdec;
+ struct pwc_dec23_private *pdec = &pdev->dec23;
- if (pwc->decompress_data == NULL) {
- pdec = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL);
- if (pdec == NULL)
- return -ENOMEM;
- pwc->decompress_data = pdec;
- }
- pdec = pwc->decompress_data;
+ mutex_init(&pdec->lock);
- if (DEVICE_USE_CODEC3(type)) {
+ if (pdec->last_cmd_valid && pdec->last_cmd == cmd[2])
+ return;
+
+ if (DEVICE_USE_CODEC3(pdev->type)) {
flags = cmd[2] & 0x18;
if (flags == 8)
pdec->nbits = 7; /* More bits, mean more bits to encode the stream, but better quality */
@@ -362,7 +351,8 @@ int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd)
pwc_crop_table[MAX_OUTER_CROP_VALUE+256+i] = 255;
#endif
- return 0;
+ pdec->last_cmd = cmd[2];
+ pdec->last_cmd_valid = 1;
}
/*
@@ -467,123 +457,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 +648,44 @@ 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,
+void pwc_dec23_decompress(struct pwc_device *pdev,
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 = &pdev->dec23;
+
+ /* 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 = pdev->height / 4;
+ bytes_per_block = pdev->width * 4;
+ plane_size = pdev->height * pdev->width;
+
+ pout_planar_y = dst;
+ pout_planar_u = dst + plane_size;
+ pout_planar_v = dst + plane_size + plane_size / 4;
+
+ while (bandlines_left--) {
+ DecompressBand23(pdec, src,
+ pout_planar_y, pout_planar_u, pout_planar_v,
+ pdev->width, pdev->width);
+ src += pdev->vbandlength;
+ pout_planar_y += bytes_per_block;
+ pout_planar_u += pdev->width;
+ pout_planar_v += pdev->width;
}
+ mutex_unlock(&pdec->lock);
}
diff --git a/drivers/media/video/pwc/pwc-dec23.h b/drivers/media/video/pwc/pwc-dec23.h
index a0ac4f3dff81..c655b1c1e6a9 100644
--- a/drivers/media/video/pwc/pwc-dec23.h
+++ b/drivers/media/video/pwc/pwc-dec23.h
@@ -25,15 +25,20 @@
#ifndef PWC_DEC23_H
#define PWC_DEC23_H
-#include "pwc.h"
+struct pwc_device;
struct pwc_dec23_private
{
+ struct mutex lock;
+
+ unsigned char last_cmd, last_cmd_valid;
+
unsigned int scalebits;
unsigned int nbitsmask, nbits; /* Number of bits of a color in the compressed stream */
unsigned int reservoir;
unsigned int nbits_in_reservoir;
+
const unsigned char *stream;
int temp_colors[16];
@@ -49,9 +54,8 @@ 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,
+void pwc_dec23_init(struct pwc_device *pdev, const unsigned char *cmd);
+void pwc_dec23_decompress(struct pwc_device *pdev,
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 01ff643e682d..122fbd0081eb 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -128,33 +128,23 @@ static struct usb_driver pwc_driver = {
#define MAX_DEV_HINTS 20
#define MAX_ISOC_ERRORS 20
-static int default_fps = 10;
#ifdef CONFIG_USB_PWC_DEBUG
int pwc_trace = PWC_DEBUG_LEVEL;
#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];
- int device_node;
- struct pwc_device *pdev;
-} device_hint[MAX_DEV_HINTS];
+static int leds[2] = { 100, 0 };
/***/
-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 +153,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 +181,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 +364,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 +376,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->pixfmt,
+ pdev->vframes, &compression, 1);
+
/* Get the current alternate interface, adjust packet size */
intf = usb_ifnum_to_if(udev, 0);
if (intf)
@@ -408,9 +404,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 +453,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 +522,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 +535,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,85 +571,60 @@ 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);
-
- pdev = video_get_drvdata(vdev);
- if (!pdev->udev)
- return -ENODEV;
+ int r = 0;
- 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);
- int hint;
-
- /* search device_hint[] table if we occupy a slot, by any chance */
- for (hint = 0; hint < MAX_DEV_HINTS; hint++)
- if (device_hint[hint].pdev == pdev)
- device_hint[hint].pdev = NULL;
-
- /* Free intermediate decompression buffer & tables */
- if (pdev->decompress_data != NULL) {
- PWC_DEBUG_MEMORY("Freeing decompression buffer at %p.\n",
- pdev->decompress_data);
- kfree(pdev->decompress_data);
- pdev->decompress_data = NULL;
- }
+ struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev);
v4l2_ctrl_handler_free(&pdev->ctrl_handler);
-
+ kfree(pdev->ctrl_buf);
kfree(pdev);
}
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 +634,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 +650,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 +659,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 +716,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);
+ pwc_set_leds(pdev, leds[0], leds[1]);
- 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 +778,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,
};
/***************************************************************************/
@@ -887,9 +792,9 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
struct usb_device *udev = interface_to_usbdev(intf);
struct pwc_device *pdev = NULL;
int vendor_id, product_id, type_id;
- int hint, rc;
+ int rc;
int features = 0;
- int video_nr = -1; /* default: use next available device */
+ int compression = 0;
int my_power_save = power_save;
char serial_number[30], *name;
@@ -1149,28 +1054,15 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
return -ENOMEM;
}
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,35 +1077,21 @@ 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);
PWC_DEBUG_PROBE("Release: %04x\n", pdev->release);
- /* Now search device_hint[] table for a match, so we can hint a node number. */
- for (hint = 0; hint < MAX_DEV_HINTS; hint++) {
- if (((device_hint[hint].type == -1) || (device_hint[hint].type == pdev->type)) &&
- (device_hint[hint].pdev == NULL)) {
- /* so far, so good... try serial number */
- if ((device_hint[hint].serial_number[0] == '*') || !strcmp(device_hint[hint].serial_number, serial_number)) {
- /* match! */
- video_nr = device_hint[hint].device_node;
- PWC_DEBUG_PROBE("Found hint, will try to register as /dev/video%d\n", video_nr);
- break;
- }
- }
+ /* Allocate USB command buffers */
+ pdev->ctrl_buf = kmalloc(sizeof(pdev->cmd_buf), GFP_KERNEL);
+ if (!pdev->ctrl_buf) {
+ PWC_ERROR("Oops, could not allocate memory for pwc_device.\n");
+ rc = -ENOMEM;
+ goto err_free_mem;
}
- /* occupy slot */
- 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 +1105,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,
+ V4L2_PIX_FMT_YUV420, 30, &compression, 1);
if (rc)
goto err_free_mem;
@@ -1239,20 +1117,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);
- 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);
+ /* 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;
}
- rc = pwc_create_sysfs_files(pdev);
- if (rc)
- goto err_video_unreg;
+ pdev->v4l2_dev.ctrl_handler = &pdev->ctrl_handler;
+ pdev->vdev.v4l2_dev = &pdev->v4l2_dev;
+
+ rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, -1);
+ if (rc < 0) {
+ PWC_ERROR("Failed to register as video device (%d).\n", rc);
+ goto err_unregister_v4l2_dev;
+ }
PWC_INFO("Registered as %s.\n", video_device_node_name(&pdev->vdev));
#ifdef CONFIG_USB_PWC_INPUT_EVDEV
@@ -1261,7 +1144,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 +1161,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 +1168,13 @@ 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);
+ kfree(pdev->ctrl_buf);
kfree(pdev);
return rc;
}
@@ -1301,27 +1182,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);
}
@@ -1329,30 +1209,19 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
* Initialization code & module stuff
*/
-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];
-static unsigned int dev_hint_nargs;
-module_param(fps, int, 0444);
#ifdef CONFIG_USB_PWC_DEBUG
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);
-MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30");
#ifdef CONFIG_USB_PWC_DEBUG
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");
MODULE_DESCRIPTION("Philips & OEM USB webcam driver");
MODULE_AUTHOR("Luc Saillard <luc@saillard.org>");
@@ -1362,122 +1231,13 @@ MODULE_VERSION( PWC_VERSION );
static int __init usb_pwc_init(void)
{
- int i;
-
-#ifdef CONFIG_USB_PWC_DEBUG
- PWC_INFO("Philips webcam module version " PWC_VERSION " loaded.\n");
- PWC_INFO("Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.\n");
- PWC_INFO("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n");
- PWC_INFO("the Creative WebCam 5 & Pro Ex, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.\n");
-
- if (pwc_trace >= 0) {
- PWC_DEBUG_MODULE("Trace options: 0x%04x\n", pwc_trace);
- }
-#endif
-
- if (fps) {
- if (fps < 4 || fps > 30) {
- PWC_ERROR("Framerate out of bounds (4-30).\n");
- return -EINVAL;
- }
- default_fps = fps;
- 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)
- led_off = leds[1];
-
- /* Big device node whoopla. Basically, it allows you to assign a
- device node (/dev/videoX) to a camera, based on its type
- & serial number. The format is [type[.serialnumber]:]node.
-
- Any camera that isn't matched by these rules gets the next
- available free device node.
- */
- for (i = 0; i < MAX_DEV_HINTS; i++) {
- char *s, *colon, *dot;
-
- /* This loop also initializes the array */
- device_hint[i].pdev = NULL;
- s = dev_hint[i];
- if (s != NULL && *s != '\0') {
- device_hint[i].type = -1; /* wildcard */
- strcpy(device_hint[i].serial_number, "*");
-
- /* parse string: chop at ':' & '/' */
- colon = dot = s;
- while (*colon != '\0' && *colon != ':')
- colon++;
- while (*dot != '\0' && *dot != '.')
- dot++;
- /* Few sanity checks */
- if (*dot != '\0' && dot > colon) {
- PWC_ERROR("Malformed camera hint: the colon must be after the dot.\n");
- return -EINVAL;
- }
-
- if (*colon == '\0') {
- /* No colon */
- if (*dot != '\0') {
- PWC_ERROR("Malformed camera hint: no colon + device node given.\n");
- return -EINVAL;
- }
- else {
- /* No type or serial number specified, just a number. */
- device_hint[i].device_node =
- simple_strtol(s, NULL, 10);
- }
- }
- else {
- /* There's a colon, so we have at least a type and a device node */
- device_hint[i].type =
- simple_strtol(s, NULL, 10);
- device_hint[i].device_node =
- simple_strtol(colon + 1, NULL, 10);
- if (*dot != '\0') {
- /* There's a serial number as well */
- int k;
-
- dot++;
- k = 0;
- while (*dot != ':' && k < 29) {
- device_hint[i].serial_number[k++] = *dot;
- dot++;
- }
- device_hint[i].serial_number[k] = '\0';
- }
- }
- PWC_TRACE("device_hint[%d]:\n", i);
- PWC_TRACE(" type : %d\n", device_hint[i].type);
- PWC_TRACE(" serial# : %s\n", device_hint[i].serial_number);
- PWC_TRACE(" node : %d\n", device_hint[i].device_node);
- }
- else
- device_hint[i].type = 0; /* not filled */
- } /* ..for MAX_DEV_HINTS */
-
- PWC_DEBUG_PROBE("Registering driver at address 0x%p.\n", &pwc_driver);
return usb_register(&pwc_driver);
}
static void __exit usb_pwc_exit(void)
{
- PWC_DEBUG_MODULE("Deregistering driver.\n");
usb_deregister(&pwc_driver);
- PWC_INFO("Philips webcam module removed.\n");
}
module_init(usb_pwc_init);
module_exit(usb_pwc_exit);
-
-/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
diff --git a/drivers/media/video/pwc/pwc-kiara.h b/drivers/media/video/pwc/pwc-kiara.h
index 047dad8c15f7..8e02b7ac2139 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 0b031336eab8..9be5adffa874 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,10 @@ 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 a6e22224c95f..270c5b9010f6 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 51265092bd31..b65903fbcf0d 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 a10ff6b64acf..f495eeb5403a 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,45 @@ 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,
+ pixelformat, 30, &compression, 0);
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;
-
+ 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 +540,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 +612,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 +640,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;
@@ -766,33 +772,33 @@ static int pwc_set_autogain_expo(struct pwc_device *pdev)
static int pwc_set_motor(struct pwc_device *pdev)
{
int ret;
- u8 buf[4];
- buf[0] = 0;
+ pdev->ctrl_buf[0] = 0;
if (pdev->motor_pan_reset->is_new)
- buf[0] |= 0x01;
+ pdev->ctrl_buf[0] |= 0x01;
if (pdev->motor_tilt_reset->is_new)
- buf[0] |= 0x02;
+ pdev->ctrl_buf[0] |= 0x02;
if (pdev->motor_pan_reset->is_new || pdev->motor_tilt_reset->is_new) {
ret = send_control_msg(pdev, SET_MPT_CTL,
- PT_RESET_CONTROL_FORMATTER, buf, 1);
+ PT_RESET_CONTROL_FORMATTER,
+ pdev->ctrl_buf, 1);
if (ret < 0)
return ret;
}
- memset(buf, 0, sizeof(buf));
+ memset(pdev->ctrl_buf, 0, 4);
if (pdev->motor_pan->is_new) {
- buf[0] = pdev->motor_pan->val & 0xFF;
- buf[1] = (pdev->motor_pan->val >> 8);
+ pdev->ctrl_buf[0] = pdev->motor_pan->val & 0xFF;
+ pdev->ctrl_buf[1] = (pdev->motor_pan->val >> 8);
}
if (pdev->motor_tilt->is_new) {
- buf[2] = pdev->motor_tilt->val & 0xFF;
- buf[3] = (pdev->motor_tilt->val >> 8);
+ pdev->ctrl_buf[2] = pdev->motor_tilt->val & 0xFF;
+ pdev->ctrl_buf[3] = (pdev->motor_tilt->val >> 8);
}
if (pdev->motor_pan->is_new || pdev->motor_tilt->is_new) {
ret = send_control_msg(pdev, SET_MPT_CTL,
PT_RELATIVE_CONTROL_FORMATTER,
- buf, sizeof(buf));
+ pdev->ctrl_buf, 4);
if (ret < 0)
return ret;
}
@@ -806,8 +812,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 +895,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 +917,6 @@ static int pwc_s_ctrl(struct v4l2_ctrl *ctrl)
leave:
mutex_unlock(&pdev->udevlock);
- mutex_lock(&pdev->modlock);
return ret;
}
@@ -933,9 +946,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 +969,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 +1040,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 +1067,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;
}
@@ -1078,20 +1089,69 @@ static int pwc_enum_frameintervals(struct file *file, void *fh,
return 0;
}
-static int pwc_log_status(struct file *file, void *priv)
+static int pwc_g_parm(struct file *file, void *fh,
+ struct v4l2_streamparm *parm)
{
struct pwc_device *pdev = video_drvdata(file);
- v4l2_ctrl_handler_log_status(&pdev->ctrl_handler, PWC_NAME);
+ if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ memset(parm, 0, sizeof(*parm));
+
+ parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ parm->parm.capture.readbuffers = MIN_FRAMES;
+ parm->parm.capture.capability |= V4L2_CAP_TIMEPERFRAME;
+ parm->parm.capture.timeperframe.denominator = pdev->vframes;
+ parm->parm.capture.timeperframe.numerator = 1;
+
return 0;
}
-static long pwc_default(struct file *file, void *fh, bool valid_prio,
- int cmd, void *arg)
+static int pwc_s_parm(struct file *file, void *fh,
+ struct v4l2_streamparm *parm)
{
struct pwc_device *pdev = video_drvdata(file);
+ int compression = 0;
+ int ret, fps;
- return pwc_ioctl(pdev, cmd, arg);
+ if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+ parm->parm.capture.timeperframe.numerator == 0)
+ return -EINVAL;
+
+ if (pwc_test_n_set_capt_file(pdev, file))
+ return -EBUSY;
+
+ fps = parm->parm.capture.timeperframe.denominator /
+ parm->parm.capture.timeperframe.numerator;
+
+ mutex_lock(&pdev->udevlock);
+ if (!pdev->udev) {
+ ret = -ENODEV;
+ goto leave;
+ }
+
+ if (pdev->iso_init) {
+ ret = -EBUSY;
+ goto leave;
+ }
+
+ ret = pwc_set_video_mode(pdev, pdev->width, pdev->height, pdev->pixfmt,
+ fps, &compression, 0);
+
+ pwc_g_parm(file, fh, parm);
+
+leave:
+ mutex_unlock(&pdev->udevlock);
+ return ret;
+}
+
+static int pwc_log_status(struct file *file, void *priv)
+{
+ struct pwc_device *pdev = video_drvdata(file);
+
+ v4l2_ctrl_handler_log_status(&pdev->ctrl_handler, PWC_NAME);
+ return 0;
}
const struct v4l2_ioctl_ops pwc_ioctl_ops = {
@@ -1112,8 +1172,6 @@ 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,
+ .vidioc_g_parm = pwc_g_parm,
+ .vidioc_s_parm = pwc_s_parm,
};
-
-
-/* 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 0e4e2d7b7872..e4d4d711dd1f 100644
--- a/drivers/media/video/pwc/pwc.h
+++ b/drivers/media/video/pwc/pwc.h
@@ -35,14 +35,17 @@
#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>
+#include "pwc-dec1.h"
+#include "pwc-dec23.h"
/* Version block */
#define PWC_VERSION "10.0.15"
@@ -106,6 +109,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
@@ -128,9 +134,6 @@
#define DEVICE_USE_CODEC3(x) ((x)>=700)
#define DEVICE_USE_CODEC23(x) ((x)>=675)
-/* from pwc-dec.h */
-#define PWCX_FLAG_PLANAR 0x0001
-
/* Request types: video */
#define SET_LUM_CTL 0x01
#define GET_LUM_CTL 0x02
@@ -186,6 +189,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,39 +219,36 @@ 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 */
- int cmd_len;
unsigned char cmd_buf[13];
+ unsigned char *ctrl_buf;
struct urb *urbs[MAX_ISO_BUFS];
char iso_init;
@@ -253,7 +271,10 @@ struct pwc_device
int frame_total_size; /* including header & trailer */
int drop_frames;
- void *decompress_data; /* private data for decompression engine */
+ union { /* private data for decompression engine */
+ struct pwc_dec1_private dec1;
+ struct pwc_dec23_private dec23;
+ };
/*
* We have an 'image' and a 'view', where 'image' is the fixed-size img
@@ -262,21 +283,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 */
+ int width, height; /* current resolution */
- /*** 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 */
-
- /*
- * 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 +336,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 +354,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 pixfmt, int frames, int *compression, int send_to_cam);
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 +386,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 79fb22c89ae9..0bd7da26d018 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 2cc3b9166724..a9e9653beeb4 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);
@@ -689,7 +693,7 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx,
mf->code = 0;
continue;
}
- if (mf->width != tfmt->width || mf->width != tfmt->width) {
+ if (mf->width != tfmt->width || mf->height != tfmt->height) {
u32 fcc = ffmt->fourcc;
tfmt->width = mf->width;
tfmt->height = mf->height;
@@ -698,7 +702,8 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx,
NULL, &fcc, FIMC_SD_PAD_SOURCE);
if (ffmt && ffmt->mbus_code)
mf->code = ffmt->mbus_code;
- if (mf->width != tfmt->width || mf->width != tfmt->width)
+ if (mf->width != tfmt->width ||
+ mf->height != tfmt->height)
continue;
tfmt->code = mf->code;
}
@@ -706,7 +711,7 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx,
ret = v4l2_subdev_call(csis, pad, set_fmt, NULL, &sfmt);
if (mf->code == tfmt->code &&
- mf->width == tfmt->width && mf->width == tfmt->width)
+ mf->width == tfmt->width && mf->height == tfmt->height)
break;
}
@@ -812,6 +817,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 +1244,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 07c6254faee3..81bcbb9492ea 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,59 +789,77 @@ 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);
+ V4L2_CID_ROTATE, 0, 270, 90, 0);
ctx->ctrl_hflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops,
- V4L2_CID_VFLIP, 0, 1, 1, 0);
+ V4L2_CID_HFLIP, 0, 1, 1, 0);
ctx->ctrl_vflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops,
- V4L2_CID_ROTATE, 0, 270, 90, 0);
+ V4L2_CID_VFLIP, 0, 1, 1, 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 c7f01c47b20f..4e20560c73d4 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-mdevice.c b/drivers/media/video/s5p-fimc/fimc-mdevice.c
index 615c862f0360..8ea4ee116e46 100644
--- a/drivers/media/video/s5p-fimc/fimc-mdevice.c
+++ b/drivers/media/video/s5p-fimc/fimc-mdevice.c
@@ -21,7 +21,6 @@
#include <linux/pm_runtime.h>
#include <linux/types.h>
#include <linux/slab.h>
-#include <linux/version.h>
#include <media/v4l2-ctrls.h>
#include <media/media-device.h>
diff --git a/drivers/media/video/s5p-fimc/fimc-reg.c b/drivers/media/video/s5p-fimc/fimc-reg.c
index 44f5c2d1920b..15466d0529c1 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 59d79bc2f58a..130335cf62fd 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 f5691336dd5c..2709286396e1 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 c8e3b94bd91d..c7a5bc51d571 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 000000000000..2c48c416a804
--- /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 000000000000..39937cf03c88
--- /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 000000000000..02e1cf50da4e
--- /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 000000000000..febaa673d363
--- /dev/null
+++ b/drivers/media/video/s5p-g2d/g2d.c
@@ -0,0 +1,811 @@
+/*
+ * 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;
+ break;
+ 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 000000000000..5eae90107bf8
--- /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 000000000000..ddc2900d88a2
--- /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 000000000000..1105a8749c8b
--- /dev/null
+++ b/drivers/media/video/s5p-jpeg/jpeg-core.c
@@ -0,0 +1,1482 @@
+/* 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,
+ const struct v4l2_format *fmt,
+ 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 000000000000..facad6114f5e
--- /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 000000000000..e10c744e9f23
--- /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 000000000000..91f4dd5f86dd
--- /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 8be8b54eb749..83fe461af263 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/video/s5p-mfc/s5p_mfc.c
@@ -18,7 +18,6 @@
#include <linux/platform_device.h>
#include <linux/sched.h>
#include <linux/slab.h>
-#include <linux/version.h>
#include <linux/videodev2.h>
#include <linux/workqueue.h>
#include <media/videobuf2-core.h>
@@ -475,7 +474,7 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx,
ctx->mv_size = 0;
}
ctx->dpb_count = s5p_mfc_get_dpb_count();
- if (ctx->img_width == 0 || ctx->img_width == 0)
+ if (ctx->img_width == 0 || ctx->img_height == 0)
ctx->state = MFCINST_ERROR;
else
ctx->state = MFCINST_HEAD_PARSED;
@@ -1245,27 +1244,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-mfc/s5p_mfc_dec.c b/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
index 844a4d7797bc..c25ec022d267 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
@@ -165,7 +165,7 @@ static struct mfc_control controls[] = {
.maximum = 32,
.step = 1,
.default_value = 1,
- .flags = V4L2_CTRL_FLAG_VOLATILE,
+ .is_volatile = 1,
},
};
diff --git a/drivers/media/video/s5p-tv/hdmi_drv.c b/drivers/media/video/s5p-tv/hdmi_drv.c
index 0279e6e89feb..8b41a0410ab1 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 51ad59b30358..1597078c4a50 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 de8270c2b6e7..b93a21f5aa13 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 b47d0c06ecf5..7884baeff76a 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 f3bb2e34cb51..3d13a636877b 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 8cec67ef48c9..059e7749ce95 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 5cfdbc78b918..0ef5484696b6 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 0f9fb99adeb4..065d0f6be4a0 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 ca65cda3e101..5fbb4e49495c 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 1e4ef1669887..089fa0fb5c94 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 d4ee24bf6928..22ecd7297d2d 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 57e646bb48b3..b7a99bee2f98 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 9cf7914f6f90..417034eb6ad2 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 9b550687213a..42fba4f93c72 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 466e1b02f91f..a7f58a998752 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/saa7164/saa7164-cards.c b/drivers/media/video/saa7164/saa7164-cards.c
index 971591d6450f..5b72da5ce418 100644
--- a/drivers/media/video/saa7164/saa7164-cards.c
+++ b/drivers/media/video/saa7164/saa7164-cards.c
@@ -269,8 +269,6 @@ struct saa7164_board saa7164_boards[] = {
.portb = SAA7164_MPEG_DVB,
.portc = SAA7164_MPEG_ENCODER,
.portd = SAA7164_MPEG_ENCODER,
- .portc = SAA7164_MPEG_ENCODER,
- .portd = SAA7164_MPEG_ENCODER,
.porte = SAA7164_MPEG_VBI,
.portf = SAA7164_MPEG_VBI,
.chiprev = SAA7164_CHIP_REV3,
@@ -333,8 +331,6 @@ struct saa7164_board saa7164_boards[] = {
.portd = SAA7164_MPEG_ENCODER,
.porte = SAA7164_MPEG_VBI,
.portf = SAA7164_MPEG_VBI,
- .porte = SAA7164_MPEG_VBI,
- .portf = SAA7164_MPEG_VBI,
.chiprev = SAA7164_CHIP_REV3,
.unit = {{
.id = 0x28,
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
index c51decfcae19..f854d85a387c 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 8a652b53ff7e..05286500b4d4 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 7025be129286..c2882fa5be85 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 62e4312515cb..b82710745ba8 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 4402a8a74f7a..f59ccade07c8 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 b7fb5a5cad7e..d427f8436c70 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 a0895bf07487..4ed1c7c28ae7 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 56564e6aaac2..5dd73b7857d1 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 d0da11ae19df..30fcb117e898 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/tlg2300/pd-main.c b/drivers/media/video/tlg2300/pd-main.c
index 129f135d5a5f..c096b3f74200 100644
--- a/drivers/media/video/tlg2300/pd-main.c
+++ b/drivers/media/video/tlg2300/pd-main.c
@@ -374,7 +374,7 @@ static inline void set_map_flags(struct poseidon *pd, struct usb_device *udev)
}
#endif
-static bool check_firmware(struct usb_device *udev, int *down_firmware)
+static int check_firmware(struct usb_device *udev, int *down_firmware)
{
void *buf;
int ret;
@@ -398,7 +398,7 @@ static bool check_firmware(struct usb_device *udev, int *down_firmware)
*down_firmware = 1;
return firmware_download(udev);
}
- return ret;
+ return 0;
}
static int poseidon_probe(struct usb_interface *interface,
diff --git a/drivers/media/video/tm6000/Kconfig b/drivers/media/video/tm6000/Kconfig
index 114eec8a630a..a43b77abd931 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 7d675c72fd47..bd07ec707956 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 ff939bc0e0b9..034659b13174 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 9783616a0da2..22cc0116deb6 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 5e6c129a4beb..e1f3f66e1e63 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 0290bbf00c3e..c7e23e3dd75e 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 405d12729d05..7844607dd45a 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 7f491b6de933..a38c251ed57b 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 9a4145dc3d87..9dc0831d813f 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 1e5ace0b5d10..bc13db736e24 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 2777e514eff2..27ba659cfa85 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 11cc980b0cd5..4059ea178c2d 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 926f03931156..dd26cacd0556 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 6abaa16ae136..6be9910a6e24 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 7875e80cb2ff..236c559d5f51 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 9bbe61700fd5..65d065aa6091 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 d7f97513b289..89fec029e924 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 2956a7637219..6c197da531b2 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 2071ca8a2f03..c26d12fdb8f4 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 254d32688843..0efd3b10b353 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 000000000000..14561a5abb79
--- /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 656d4c9e3b9f..a240d43d15d1 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 74bbe8f18f3e..8510e7259e76 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 677691c44500..518f77d3a4d8 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 dadf11f704dc..2ae4f880ea05 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 b015e8e5e8b0..c7e69b8f81c9 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 4c1392ebcd4b..67f88d85bb16 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 c68531b88279..af4419e6c658 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 0f415dade05a..cccd42be718a 100644
--- a/drivers/media/video/v4l2-ctrls.c
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -465,8 +465,9 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_CHROMA_GAIN: return "Chroma Gain";
case V4L2_CID_ILLUMINATORS_1: return "Illuminator 1";
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_MIN_BUFFERS_FOR_CAPTURE: return "Min Number of Capture Buffers";
+ case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT: return "Min 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! */
@@ -505,25 +506,25 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_MPEG_VIDEO_MUTE_YUV: return "Video Mute YUV";
case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE: return "Decoder Slice Interface";
case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER: return "MPEG4 Loop Filter Enable";
- case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB: return "The Number of Intra Refresh MBs";
+ case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB: return "Number of Intra Refresh MBs";
case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE: return "Frame Level Rate Control Enable";
case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE: return "H264 MB Level Rate Control";
case V4L2_CID_MPEG_VIDEO_HEADER_MODE: return "Sequence Header Mode";
- case V4L2_CID_MPEG_VIDEO_MAX_REF_PIC: return "The Max Number of Reference Picture";
+ case V4L2_CID_MPEG_VIDEO_MAX_REF_PIC: return "Max Number of Reference Pics";
case V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP: return "H263 I-Frame QP Value";
- case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP: return "H263 P frame QP Value";
- case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP: return "H263 B frame QP Value";
+ case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP: return "H263 P-Frame QP Value";
+ case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP: return "H263 B-Frame QP Value";
case V4L2_CID_MPEG_VIDEO_H263_MIN_QP: return "H263 Minimum QP Value";
case V4L2_CID_MPEG_VIDEO_H263_MAX_QP: return "H263 Maximum QP Value";
case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP: return "H264 I-Frame QP Value";
- case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP: return "H264 P frame QP Value";
- case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP: return "H264 B frame QP Value";
+ case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP: return "H264 P-Frame QP Value";
+ case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP: return "H264 B-Frame QP Value";
case V4L2_CID_MPEG_VIDEO_H264_MAX_QP: return "H264 Maximum QP Value";
case V4L2_CID_MPEG_VIDEO_H264_MIN_QP: return "H264 Minimum QP Value";
case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM: return "H264 8x8 Transform Enable";
case V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE: return "H264 CPB Buffer Size";
- case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE: return "H264 Entorpy Mode";
- case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD: return "H264 I Period";
+ case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE: return "H264 Entropy Mode";
+ case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD: return "H264 I-Frame Period";
case V4L2_CID_MPEG_VIDEO_H264_LEVEL: return "H264 Level";
case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA: return "H264 Loop Filter Alpha Offset";
case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA: return "H264 Loop Filter Beta Offset";
@@ -534,16 +535,16 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE: return "Aspect Ratio VUI Enable";
case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC: return "VUI Aspect Ratio IDC";
case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP: return "MPEG4 I-Frame QP Value";
- case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP: return "MPEG4 P frame QP Value";
- case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP: return "MPEG4 B frame QP Value";
+ case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP: return "MPEG4 P-Frame QP Value";
+ case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP: return "MPEG4 B-Frame QP Value";
case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP: return "MPEG4 Minimum QP Value";
case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP: return "MPEG4 Maximum QP Value";
case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL: return "MPEG4 Level";
case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: return "MPEG4 Profile";
case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL: return "Quarter Pixel Search Enable";
- case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES: return "The Maximum Bytes Per Slice";
- case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB: return "The Number of MB in a Slice";
- case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE: return "The Slice Partitioning Method";
+ case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES: return "Maximum Bytes in a Slice";
+ case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB: return "Number of MBs in a Slice";
+ case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE: return "Slice Partitioning Method";
case V4L2_CID_MPEG_VIDEO_VBV_SIZE: return "VBV Buffer Size";
/* CAMERA controls */
@@ -579,7 +580,7 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_AUDIO_LIMITER_ENABLED: return "Audio Limiter Feature Enabled";
case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: return "Audio Limiter Release Time";
case V4L2_CID_AUDIO_LIMITER_DEVIATION: return "Audio Limiter Deviation";
- case V4L2_CID_AUDIO_COMPRESSION_ENABLED: return "Audio Compression Feature Enabled";
+ case V4L2_CID_AUDIO_COMPRESSION_ENABLED: return "Audio Compression Enabled";
case V4L2_CID_AUDIO_COMPRESSION_GAIN: return "Audio Compression Gain";
case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD: return "Audio Compression Threshold";
case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME: return "Audio Compression Attack Time";
@@ -587,24 +588,24 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_PILOT_TONE_ENABLED: return "Pilot Tone Feature Enabled";
case V4L2_CID_PILOT_TONE_DEVIATION: return "Pilot Tone Deviation";
case V4L2_CID_PILOT_TONE_FREQUENCY: return "Pilot Tone Frequency";
- case V4L2_CID_TUNE_PREEMPHASIS: return "Pre-emphasis settings";
+ case V4L2_CID_TUNE_PREEMPHASIS: return "Pre-Emphasis";
case V4L2_CID_TUNE_POWER_LEVEL: return "Tune Power Level";
case V4L2_CID_TUNE_ANTENNA_CAPACITOR: return "Tune Antenna Capacitor";
/* Flash controls */
- case V4L2_CID_FLASH_CLASS: return "Flash controls";
- case V4L2_CID_FLASH_LED_MODE: return "LED mode";
- case V4L2_CID_FLASH_STROBE_SOURCE: return "Strobe source";
+ case V4L2_CID_FLASH_CLASS: return "Flash Controls";
+ case V4L2_CID_FLASH_LED_MODE: return "LED Mode";
+ case V4L2_CID_FLASH_STROBE_SOURCE: return "Strobe Source";
case V4L2_CID_FLASH_STROBE: return "Strobe";
- case V4L2_CID_FLASH_STROBE_STOP: return "Stop strobe";
- case V4L2_CID_FLASH_STROBE_STATUS: return "Strobe status";
- case V4L2_CID_FLASH_TIMEOUT: return "Strobe timeout";
- case V4L2_CID_FLASH_INTENSITY: return "Intensity, flash mode";
- case V4L2_CID_FLASH_TORCH_INTENSITY: return "Intensity, torch mode";
- case V4L2_CID_FLASH_INDICATOR_INTENSITY: return "Intensity, indicator";
+ case V4L2_CID_FLASH_STROBE_STOP: return "Stop Strobe";
+ case V4L2_CID_FLASH_STROBE_STATUS: return "Strobe Status";
+ case V4L2_CID_FLASH_TIMEOUT: return "Strobe Timeout";
+ case V4L2_CID_FLASH_INTENSITY: return "Intensity, Flash Mode";
+ case V4L2_CID_FLASH_TORCH_INTENSITY: return "Intensity, Torch Mode";
+ case V4L2_CID_FLASH_INDICATOR_INTENSITY: return "Intensity, Indicator";
case V4L2_CID_FLASH_FAULT: return "Faults";
case V4L2_CID_FLASH_CHARGE: return "Charge";
- case V4L2_CID_FLASH_READY: return "Ready to strobe";
+ case V4L2_CID_FLASH_READY: return "Ready to Strobe";
default:
return NULL;
@@ -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 a5c9ed128b97..96e9615663e9 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 0edd618b9ddf..1f203b85a637 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 e1da8fc9dd2f..3f623859a337 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);
@@ -1767,6 +1871,7 @@ static long __video_do_ioctl(struct file *file,
case VIDIOC_S_FREQUENCY:
{
struct v4l2_frequency *p = arg;
+ enum v4l2_tuner_type type;
if (!ops->vidioc_s_frequency)
break;
@@ -1774,9 +1879,14 @@ static long __video_do_ioctl(struct file *file,
ret = ret_prio;
break;
}
+ type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
+ V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n",
p->tuner, p->type, p->frequency);
- ret = ops->vidioc_s_frequency(file, fh, p);
+ if (p->type != type)
+ ret = -EINVAL;
+ else
+ ret = ops->vidioc_s_frequency(file, fh, p);
break;
}
case VIDIOC_G_SLICED_VBI_CAP:
@@ -2226,6 +2336,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 65ade5f03c2e..41d118ee2de6 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 cbf13d09b4ac..20f7237b8242 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 3de7c7e4402d..59cb54aa2946 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 95a3f5e82aef..2e8f1df775b6 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 3bad8b105fea..25c3b360e1ad 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 71a7a78c3fc0..c41cb60245d6 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 a3a884234059..4e789a178f8a 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 52a0a3736c82..4d7391ec8001 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 e8a27844bf39..e86173bd1327 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/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c
index f6d26419445e..4c09ab781ec3 100644
--- a/drivers/media/video/zoran/zoran_driver.c
+++ b/drivers/media/video/zoran/zoran_driver.c
@@ -1958,7 +1958,6 @@ static int zoran_g_fbuf(struct file *file, void *__fh,
mutex_unlock(&zr->resource_lock);
fb->fmt.colorspace = V4L2_COLORSPACE_SRGB;
fb->fmt.field = V4L2_FIELD_INTERLACED;
- fb->flags = V4L2_FBUF_FLAG_OVERLAY;
fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
return 0;
diff --git a/drivers/media/video/zoran/zr36060.c b/drivers/media/video/zoran/zr36060.c
index 5e4f57cbf314..f08546fe2234 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 6ce70e9615d3..5319e9b65847 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 668f5c6a0399..29b2172ae18f 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 b7aacf47703a..6902b83eb1b4 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 e017dc88622a..f93dd9571c3c 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 053208d31fb9..cd13e9f2f5e6 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
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 47591fc7d0d2..b953bab934f7 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
@@ -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 02c42015ba51..3aa36eb5c79b 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 ec10629a0b0b..bd56a764dea1 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 b7b2d3483fd4..72006940937a 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 d3d572b2317b..53e2a80f42fa 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 dedb7f65cea6..9a0211aa8897 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 e985d1701a83..c39fc716e1dc 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 9be541c6b004..087fecd71ce0 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 f20feefac190..c28d4eb1eff0 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 155fa0407882..315fef5d466a 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 8ad88da647b9..7710227d284e 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 97c27762174f..b76657eb0c51 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 5c2a06acb77f..a9223ed1b7c5 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 ef39528088f2..87662a17dec6 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 ea1169b04779..abc421364a45 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-i2c.c b/drivers/mfd/max8925-i2c.c
index 0219115e00c7..d9e4b36edee9 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 5be53ae9b61c..cb83a7ab53e7 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 de4096aee248..6ef56d28c056 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 e9619acc0237..7122386b4e3c 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 84815f9ef636..63be60bc3455 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 2dab02d9ac8b..9adc2eb69492 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 3f565ef3e149..68ac2c55d5ae 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 aed0d2a9b032..3927c17e4175 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 000000000000..e075c113eec6
--- /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 000000000000..de76dfb6f0ad
--- /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 df3702c1756d..f4d86117f44a 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 000000000000..373f423b1181
--- /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 000000000000..b58c43c7ea93
--- /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 2963689cf45c..e07947e56b2a 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 e4ee38956583..7b8e13f5b764 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 91ad21ef7721..2d9e8799e733 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 71bc835324d8..d20a284ad4ba 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 af9ab0e5ca64..4fb0e6c8e8fe 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 02d65692ceb4..0ba26fb12cf5 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 a56be931551c..95c0d7978bec 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 c1da84bc1573..01cf5012a08f 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 6d71e0d25744..27d3302d56b8 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 61e70cfaa774..e04e04ddc15e 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 ae51ab5d0e5d..838ce4eb444e 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 29f11e0765fe..b69bb517b102 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 834f824d3c11..456ecb5ac4fe 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 a764676f0922..d905f5171153 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 268f80fd0439..dda86293dc9f 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 b281217334eb..91c4f25e0e55 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 38ffbd50a0d2..40ec3c118868 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 d698703dbd46..b73cc15e0081 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 0a2b8d41a702..f5e54fae8ada 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 ac8da1d439da..cb15609b0a48 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 f4747a4a9a93..bec4d0539160 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 8d6a9a969dbc..62ef3254105f 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 e81cc31e4202..dd1caaac55e4 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 5fe5de166adb..d955faaf27c4 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 62b4626f4561..2204893444a6 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/misc/Kconfig b/drivers/misc/Kconfig
index 5664696f2d3a..6a1a092db146 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 b26495a02554..3e1d80106f04 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 2208a9d52622..d7a9aa14e5d5 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 eb5cd28bc6d8..a2d25e4857e3 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 b1f4563be9ae..701eb600b127 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 29d12a70eb1b..a981e2a42f92 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 000000000000..d74ef41aabd5
--- /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 12eef393e216..400756ec7c49 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 1e0e27cbe987..0cad48a284a8 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 e99bdc18002d..759714ed6bee 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 dcad59cbfef1..2517547b4366 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 639501970b41..dca4428380f1 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 6be49249895a..5d011a39dfff 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 000000000000..082202ae4a03
--- /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 950b97d7412a..f545a3e6eb80 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 14664f1fb16f..3bdafbca354f 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 3923880118b6..9ab5b17d488a 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 d31c78b72b0f..30055f2b0d44 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 d240427c1246..59b9ba52e66a 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 f2a05ea40f2a..c63ad03c29c7 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 3ab565e32a6a..bd7bacc950dc 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 b1f3168f791b..8f6f5ac131fc 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 b0517cc06200..d29e20630eed 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 b4b83f302e32..745f8fce2519 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 f437c3e6f3aa..947faa5d2ce4 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 a7ee50271465..fcfe1eb5acc8 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 5d3b9ae64523..dbd0c8a4e98a 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 0371bf502249..03666174ca48 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 ce2a47b71dd6..83693fd7c6b3 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 3aaeb0841914..0e342793ff14 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 72c071f6e001..df392a1143f2 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 74218ad677e4..c8852a8128a9 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 92946b84e9fa..273306c68d58 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 fa8dd2fda4b2..0d955ffaf44e 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 80d8eb143b48..1d14cda95e56 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 8e0fbe994047..4184b7946bbf 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 973011f9a298..382c835d217c 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 d1fb561e089d..fd0c661bbad3 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 fc4356e00d46..cb2dc0e75ba7 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 720f99334a7f..1bcfd6dbb5cc 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 b4257e700617..28a870804f60 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 a81312c91f70..46fd1fd1b605 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 38ebc4ea259f..d601e41af282 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 c3b08f111942..b97b2f5dafdb 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 01e5f627e0f0..ff4adc018041 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 3619adc7d9fc..0ce088ae0228 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 000000000000..a611217769f5
--- /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 6878a94626bc..7165e6a09274 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 7a039c3cb1f1..dbb75bfbcffb 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 15673a7ee6a5..f29695683556 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 9a20d1f55bb7..1af756ee0f9a 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 63cc8b6a1c9e..b7f8b33c5f19 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 e2e18d3f949c..78a36eba4df0 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 19ed580f2cab..8d66706824a6 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 a04d4d0c6fd2..ad265b96b75b 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 d5505f3fe2a1..f5d8b53be333 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 41ae6466bd83..58da3c44acc5 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 f70d04664cac..43d962829f8e 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 a4ea10242787..113ce6c9cf32 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 3020f98218f0..a95e6d901726 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 86f259cdfcbc..7a6e6cc8f8b8 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 4208b3958069..abad01b37cfb 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 2ec978bc32ba..3135a1a5d75d 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/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c
index 7dd3700f2303..73abbc3e093e 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 2a56fc6f399a..7f680420bfab 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 8544d6bf50a0..5c3d719c37e6 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 f20f393bfda6..769a4e096b3c 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 3320a50ba4f0..ad76592fb2f4 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 64fbb0021825..ead2cd16ba75 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/vtbl.c b/drivers/mtd/ubi/vtbl.c
index 9ad18da1891d..17cec0c01544 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/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 342626f4bc46..f820b26b9db3 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -909,16 +909,12 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[])
}
}
-/* hw is a boolean parameter that determines whether we should try and
- * set the hw address of the device as well as the hw address of the
- * net_device
- */
-static int alb_set_slave_mac_addr(struct slave *slave, u8 addr[], int hw)
+static int alb_set_slave_mac_addr(struct slave *slave, u8 addr[])
{
struct net_device *dev = slave->dev;
struct sockaddr s_addr;
- if (!hw) {
+ if (slave->bond->params.mode == BOND_MODE_TLB) {
memcpy(dev->dev_addr, addr, dev->addr_len);
return 0;
}
@@ -948,8 +944,8 @@ static void alb_swap_mac_addr(struct bonding *bond, struct slave *slave1, struct
u8 tmp_mac_addr[ETH_ALEN];
memcpy(tmp_mac_addr, slave1->dev->dev_addr, ETH_ALEN);
- alb_set_slave_mac_addr(slave1, slave2->dev->dev_addr, bond->alb_info.rlb_enabled);
- alb_set_slave_mac_addr(slave2, tmp_mac_addr, bond->alb_info.rlb_enabled);
+ alb_set_slave_mac_addr(slave1, slave2->dev->dev_addr);
+ alb_set_slave_mac_addr(slave2, tmp_mac_addr);
}
@@ -1096,8 +1092,7 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav
/* Try setting slave mac to bond address and fall-through
to code handling that situation below... */
- alb_set_slave_mac_addr(slave, bond->dev->dev_addr,
- bond->alb_info.rlb_enabled);
+ alb_set_slave_mac_addr(slave, bond->dev->dev_addr);
}
/* The slave's address is equal to the address of the bond.
@@ -1133,8 +1128,7 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav
}
if (free_mac_slave) {
- alb_set_slave_mac_addr(slave, free_mac_slave->perm_hwaddr,
- bond->alb_info.rlb_enabled);
+ alb_set_slave_mac_addr(slave, free_mac_slave->perm_hwaddr);
pr_warning("%s: Warning: the hw address of slave %s is in use by the bond; giving it the hw address of %s\n",
bond->dev->name, slave->dev->name,
@@ -1491,8 +1485,7 @@ int bond_alb_init_slave(struct bonding *bond, struct slave *slave)
{
int res;
- res = alb_set_slave_mac_addr(slave, slave->perm_hwaddr,
- bond->alb_info.rlb_enabled);
+ res = alb_set_slave_mac_addr(slave, slave->perm_hwaddr);
if (res) {
return res;
}
@@ -1643,8 +1636,7 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
alb_swap_mac_addr(bond, swap_slave, new_slave);
} else {
/* set the new_slave to the bond mac address */
- alb_set_slave_mac_addr(new_slave, bond->dev->dev_addr,
- bond->alb_info.rlb_enabled);
+ alb_set_slave_mac_addr(new_slave, bond->dev->dev_addr);
}
if (swap_slave) {
@@ -1704,8 +1696,7 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr)
alb_swap_mac_addr(bond, swap_slave, bond->curr_active_slave);
alb_fasten_mac_swap(bond, swap_slave, bond->curr_active_slave);
} else {
- alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr,
- bond->alb_info.rlb_enabled);
+ alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr);
read_lock(&bond->lock);
alb_send_learning_packets(bond->curr_active_slave, bond_dev->dev_addr);
diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c
index 7fc4e81d4d43..325391d19bad 100644
--- a/drivers/net/dsa/mv88e6060.c
+++ b/drivers/net/dsa/mv88e6060.c
@@ -9,6 +9,7 @@
*/
#include <linux/list.h>
+#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/phy.h>
#include <net/dsa.h>
diff --git a/drivers/net/dsa/mv88e6123_61_65.c b/drivers/net/dsa/mv88e6123_61_65.c
index c0a458fc698f..c17c75b9f531 100644
--- a/drivers/net/dsa/mv88e6123_61_65.c
+++ b/drivers/net/dsa/mv88e6123_61_65.c
@@ -9,6 +9,7 @@
*/
#include <linux/list.h>
+#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/phy.h>
#include <net/dsa.h>
@@ -20,12 +21,25 @@ static char *mv88e6123_61_65_probe(struct mii_bus *bus, int sw_addr)
ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), 0x03);
if (ret >= 0) {
- ret &= 0xfff0;
- if (ret == 0x1210)
+ if (ret == 0x1212)
+ return "Marvell 88E6123 (A1)";
+ if (ret == 0x1213)
+ return "Marvell 88E6123 (A2)";
+ if ((ret & 0xfff0) == 0x1210)
return "Marvell 88E6123";
- if (ret == 0x1610)
+
+ if (ret == 0x1612)
+ return "Marvell 88E6161 (A1)";
+ if (ret == 0x1613)
+ return "Marvell 88E6161 (A2)";
+ if ((ret & 0xfff0) == 0x1610)
return "Marvell 88E6161";
- if (ret == 0x1650)
+
+ if (ret == 0x1652)
+ return "Marvell 88E6165 (A1)";
+ if (ret == 0x1653)
+ return "Marvell 88e6165 (A2)";
+ if ((ret & 0xfff0) == 0x1650)
return "Marvell 88E6165";
}
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index e0eb68243834..55888b06d8b4 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -9,6 +9,7 @@
*/
#include <linux/list.h>
+#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/phy.h>
#include <net/dsa.h>
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 5467c040824a..a2c62c2f30ee 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -9,6 +9,7 @@
*/
#include <linux/list.h>
+#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/phy.h>
#include <net/dsa.h>
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 2b731b253598..03f3935fd8c2 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -3117,7 +3117,7 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index)
int rx_ring_size = 0;
#ifdef BCM_CNIC
- if (IS_MF_ISCSI_SD(bp)) {
+ if (!bp->rx_ring_size && IS_MF_ISCSI_SD(bp)) {
rx_ring_size = MIN_RX_SIZE_NONTPA;
bp->rx_ring_size = rx_ring_size;
} else
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
index f99c6e312a5d..31a8b38ab15e 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
@@ -1738,7 +1738,7 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode)
struct bnx2x_fp_txdata *txdata = &fp_tx->txdata[0];
u16 tx_start_idx, tx_idx;
u16 rx_start_idx, rx_idx;
- u16 pkt_prod, bd_prod, rx_comp_cons;
+ u16 pkt_prod, bd_prod;
struct sw_tx_bd *tx_buf;
struct eth_tx_start_bd *tx_start_bd;
struct eth_tx_parse_bd_e1x *pbd_e1x = NULL;
@@ -1873,8 +1873,7 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode)
if (rx_idx != rx_start_idx + num_pkts)
goto test_loopback_exit;
- rx_comp_cons = le16_to_cpu(fp_rx->rx_comp_cons);
- cqe = &fp_rx->rx_comp_ring[RCQ_BD(rx_comp_cons)];
+ cqe = &fp_rx->rx_comp_ring[RCQ_BD(fp_rx->rx_comp_cons)];
cqe_fp_flags = cqe->fast_path_cqe.type_error_flags;
cqe_fp_type = cqe_fp_flags & ETH_FAST_PATH_RX_CQE_TYPE;
if (!CQE_TYPE_FAST(cqe_fp_type) || (cqe_fp_flags & ETH_RX_ERROR_FALGS))
@@ -2121,18 +2120,16 @@ static int bnx2x_get_sset_count(struct net_device *dev, int stringset)
case ETH_SS_STATS:
if (is_multi(bp)) {
num_stats = bnx2x_num_stat_queues(bp) *
- BNX2X_NUM_Q_STATS;
- if (!IS_MF_MODE_STAT(bp))
- num_stats += BNX2X_NUM_STATS;
- } else {
- if (IS_MF_MODE_STAT(bp)) {
- num_stats = 0;
- for (i = 0; i < BNX2X_NUM_STATS; i++)
- if (IS_FUNC_STAT(i))
- num_stats++;
- } else
- num_stats = BNX2X_NUM_STATS;
- }
+ BNX2X_NUM_Q_STATS;
+ } else
+ num_stats = 0;
+ if (IS_MF_MODE_STAT(bp)) {
+ for (i = 0; i < BNX2X_NUM_STATS; i++)
+ if (IS_FUNC_STAT(i))
+ num_stats++;
+ } else
+ num_stats += BNX2X_NUM_STATS;
+
return num_stats;
case ETH_SS_TEST:
@@ -2151,8 +2148,8 @@ static void bnx2x_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
switch (stringset) {
case ETH_SS_STATS:
+ k = 0;
if (is_multi(bp)) {
- k = 0;
for_each_eth_queue(bp, i) {
memset(queue_name, 0, sizeof(queue_name));
sprintf(queue_name, "%d", i);
@@ -2163,20 +2160,17 @@ static void bnx2x_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
queue_name);
k += BNX2X_NUM_Q_STATS;
}
- if (IS_MF_MODE_STAT(bp))
- break;
- for (j = 0; j < BNX2X_NUM_STATS; j++)
- strcpy(buf + (k + j)*ETH_GSTRING_LEN,
- bnx2x_stats_arr[j].string);
- } else {
- for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) {
- if (IS_MF_MODE_STAT(bp) && IS_PORT_STAT(i))
- continue;
- strcpy(buf + j*ETH_GSTRING_LEN,
- bnx2x_stats_arr[i].string);
- j++;
- }
}
+
+
+ for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) {
+ if (IS_MF_MODE_STAT(bp) && IS_PORT_STAT(i))
+ continue;
+ strcpy(buf + (k + j)*ETH_GSTRING_LEN,
+ bnx2x_stats_arr[i].string);
+ j++;
+ }
+
break;
case ETH_SS_TEST:
@@ -2190,10 +2184,9 @@ static void bnx2x_get_ethtool_stats(struct net_device *dev,
{
struct bnx2x *bp = netdev_priv(dev);
u32 *hw_stats, *offset;
- int i, j, k;
+ int i, j, k = 0;
if (is_multi(bp)) {
- k = 0;
for_each_eth_queue(bp, i) {
hw_stats = (u32 *)&bp->fp[i].eth_q_stats;
for (j = 0; j < BNX2X_NUM_Q_STATS; j++) {
@@ -2214,46 +2207,28 @@ static void bnx2x_get_ethtool_stats(struct net_device *dev,
}
k += BNX2X_NUM_Q_STATS;
}
- if (IS_MF_MODE_STAT(bp))
- return;
- hw_stats = (u32 *)&bp->eth_stats;
- for (j = 0; j < BNX2X_NUM_STATS; j++) {
- if (bnx2x_stats_arr[j].size == 0) {
- /* skip this counter */
- buf[k + j] = 0;
- continue;
- }
- offset = (hw_stats + bnx2x_stats_arr[j].offset);
- if (bnx2x_stats_arr[j].size == 4) {
- /* 4-byte counter */
- buf[k + j] = (u64) *offset;
- continue;
- }
- /* 8-byte counter */
- buf[k + j] = HILO_U64(*offset, *(offset + 1));
+ }
+
+ hw_stats = (u32 *)&bp->eth_stats;
+ for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) {
+ if (IS_MF_MODE_STAT(bp) && IS_PORT_STAT(i))
+ continue;
+ if (bnx2x_stats_arr[i].size == 0) {
+ /* skip this counter */
+ buf[k + j] = 0;
+ j++;
+ continue;
}
- } else {
- hw_stats = (u32 *)&bp->eth_stats;
- for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) {
- if (IS_MF_MODE_STAT(bp) && IS_PORT_STAT(i))
- continue;
- if (bnx2x_stats_arr[i].size == 0) {
- /* skip this counter */
- buf[j] = 0;
- j++;
- continue;
- }
- offset = (hw_stats + bnx2x_stats_arr[i].offset);
- if (bnx2x_stats_arr[i].size == 4) {
- /* 4-byte counter */
- buf[j] = (u64) *offset;
- j++;
- continue;
- }
- /* 8-byte counter */
- buf[j] = HILO_U64(*offset, *(offset + 1));
+ offset = (hw_stats + bnx2x_stats_arr[i].offset);
+ if (bnx2x_stats_arr[i].size == 4) {
+ /* 4-byte counter */
+ buf[k + j] = (u64) *offset;
j++;
+ continue;
}
+ /* 8-byte counter */
+ buf[k + j] = HILO_U64(*offset, *(offset + 1));
+ j++;
}
}
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index ffeaaa95ed96..1e3f978ee6da 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -941,7 +941,7 @@ void bnx2x_panic_dump(struct bnx2x *bp)
struct sw_rx_bd *sw_bd = &fp->rx_buf_ring[j];
BNX2X_ERR("fp%d: rx_bd[%x]=[%x:%x] sw_bd=[%p]\n",
- i, j, rx_bd[1], rx_bd[0], sw_bd->skb);
+ i, j, rx_bd[1], rx_bd[0], sw_bd->data);
}
start = RX_SGE(fp->rx_sge_prod);
@@ -10536,6 +10536,9 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
{
struct bnx2x *bp;
int rc;
+ bool chip_is_e1x = (board_type == BCM57710 ||
+ board_type == BCM57711 ||
+ board_type == BCM57711E);
SET_NETDEV_DEV(dev, &pdev->dev);
bp = netdev_priv(dev);
@@ -10624,7 +10627,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
REG_WR(bp, PXP2_REG_PGL_ADDR_90_F0, 0);
REG_WR(bp, PXP2_REG_PGL_ADDR_94_F0, 0);
- if (CHIP_IS_E1x(bp)) {
+ if (chip_is_e1x) {
REG_WR(bp, PXP2_REG_PGL_ADDR_88_F1, 0);
REG_WR(bp, PXP2_REG_PGL_ADDR_8C_F1, 0);
REG_WR(bp, PXP2_REG_PGL_ADDR_90_F1, 0);
@@ -10635,9 +10638,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
* Enable internal target-read (in case we are probed after PF FLR).
* Must be done prior to any BAR read access. Only for 57712 and up
*/
- if (board_type != BCM57710 &&
- board_type != BCM57711 &&
- board_type != BCM57711E)
+ if (!chip_is_e1x)
REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1);
/* Reset the load counter */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
index 5ac616093f9f..cb6339c35571 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
@@ -50,6 +50,7 @@ static inline void bnx2x_exe_queue_init(struct bnx2x *bp,
int exe_len,
union bnx2x_qable_obj *owner,
exe_q_validate validate,
+ exe_q_remove remove,
exe_q_optimize optimize,
exe_q_execute exec,
exe_q_get get)
@@ -66,6 +67,7 @@ static inline void bnx2x_exe_queue_init(struct bnx2x *bp,
/* Owner specific callbacks */
o->validate = validate;
+ o->remove = remove;
o->optimize = optimize;
o->execute = exec;
o->get = get;
@@ -1340,6 +1342,35 @@ static int bnx2x_validate_vlan_mac(struct bnx2x *bp,
}
}
+static int bnx2x_remove_vlan_mac(struct bnx2x *bp,
+ union bnx2x_qable_obj *qo,
+ struct bnx2x_exeq_elem *elem)
+{
+ int rc = 0;
+
+ /* If consumption wasn't required, nothing to do */
+ if (test_bit(BNX2X_DONT_CONSUME_CAM_CREDIT,
+ &elem->cmd_data.vlan_mac.vlan_mac_flags))
+ return 0;
+
+ switch (elem->cmd_data.vlan_mac.cmd) {
+ case BNX2X_VLAN_MAC_ADD:
+ case BNX2X_VLAN_MAC_MOVE:
+ rc = qo->vlan_mac.put_credit(&qo->vlan_mac);
+ break;
+ case BNX2X_VLAN_MAC_DEL:
+ rc = qo->vlan_mac.get_credit(&qo->vlan_mac);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (rc != true)
+ return -EINVAL;
+
+ return 0;
+}
+
/**
* bnx2x_wait_vlan_mac - passivly wait for 5 seconds until all work completes.
*
@@ -1801,8 +1832,14 @@ static int bnx2x_vlan_mac_del_all(struct bnx2x *bp,
list_for_each_entry_safe(exeq_pos, exeq_pos_n, &exeq->exe_queue, link) {
if (exeq_pos->cmd_data.vlan_mac.vlan_mac_flags ==
- *vlan_mac_flags)
+ *vlan_mac_flags) {
+ rc = exeq->remove(bp, exeq->owner, exeq_pos);
+ if (rc) {
+ BNX2X_ERR("Failed to remove command\n");
+ return rc;
+ }
list_del(&exeq_pos->link);
+ }
}
spin_unlock_bh(&exeq->lock);
@@ -1908,6 +1945,7 @@ void bnx2x_init_mac_obj(struct bnx2x *bp,
bnx2x_exe_queue_init(bp,
&mac_obj->exe_queue, 1, qable_obj,
bnx2x_validate_vlan_mac,
+ bnx2x_remove_vlan_mac,
bnx2x_optimize_vlan_mac,
bnx2x_execute_vlan_mac,
bnx2x_exeq_get_mac);
@@ -1924,6 +1962,7 @@ void bnx2x_init_mac_obj(struct bnx2x *bp,
bnx2x_exe_queue_init(bp,
&mac_obj->exe_queue, CLASSIFY_RULES_COUNT,
qable_obj, bnx2x_validate_vlan_mac,
+ bnx2x_remove_vlan_mac,
bnx2x_optimize_vlan_mac,
bnx2x_execute_vlan_mac,
bnx2x_exeq_get_mac);
@@ -1963,6 +2002,7 @@ void bnx2x_init_vlan_obj(struct bnx2x *bp,
bnx2x_exe_queue_init(bp,
&vlan_obj->exe_queue, CLASSIFY_RULES_COUNT,
qable_obj, bnx2x_validate_vlan_mac,
+ bnx2x_remove_vlan_mac,
bnx2x_optimize_vlan_mac,
bnx2x_execute_vlan_mac,
bnx2x_exeq_get_vlan);
@@ -2009,6 +2049,7 @@ void bnx2x_init_vlan_mac_obj(struct bnx2x *bp,
bnx2x_exe_queue_init(bp,
&vlan_mac_obj->exe_queue, 1, qable_obj,
bnx2x_validate_vlan_mac,
+ bnx2x_remove_vlan_mac,
bnx2x_optimize_vlan_mac,
bnx2x_execute_vlan_mac,
bnx2x_exeq_get_vlan_mac);
@@ -2025,6 +2066,7 @@ void bnx2x_init_vlan_mac_obj(struct bnx2x *bp,
&vlan_mac_obj->exe_queue,
CLASSIFY_RULES_COUNT,
qable_obj, bnx2x_validate_vlan_mac,
+ bnx2x_remove_vlan_mac,
bnx2x_optimize_vlan_mac,
bnx2x_execute_vlan_mac,
bnx2x_exeq_get_vlan_mac);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
index 992308ff82e8..66da39f0c84a 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
@@ -161,6 +161,10 @@ typedef int (*exe_q_validate)(struct bnx2x *bp,
union bnx2x_qable_obj *o,
struct bnx2x_exeq_elem *elem);
+typedef int (*exe_q_remove)(struct bnx2x *bp,
+ union bnx2x_qable_obj *o,
+ struct bnx2x_exeq_elem *elem);
+
/**
* @return positive is entry was optimized, 0 - if not, negative
* in case of an error.
@@ -203,11 +207,18 @@ struct bnx2x_exe_queue_obj {
*/
exe_q_validate validate;
+ /**
+ * Called before removing pending commands, cleaning allocated
+ * resources (e.g., credits from validate)
+ */
+ exe_q_remove remove;
/**
* This will try to cancel the current pending commands list
* considering the new command.
*
+ * Returns the number of optimized commands or a negative error code
+ *
* Must run under exe_queue->lock
*/
exe_q_optimize optimize;
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index d529af99157d..a1f2e0fed78b 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -6667,14 +6667,9 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
iph = ip_hdr(skb);
tcp_opt_len = tcp_optlen(skb);
- if (skb_is_gso_v6(skb)) {
- hdr_len = skb_headlen(skb) - ETH_HLEN;
- } else {
- u32 ip_tcp_len;
-
- ip_tcp_len = ip_hdrlen(skb) + sizeof(struct tcphdr);
- hdr_len = ip_tcp_len + tcp_opt_len;
+ hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb) - ETH_HLEN;
+ if (!skb_is_gso_v6(skb)) {
iph->check = 0;
iph->tot_len = htons(mss + hdr_len);
}
diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/cisco/enic/enic.h
index fe0c29acdbe6..ee93a2087fe6 100644
--- a/drivers/net/ethernet/cisco/enic/enic.h
+++ b/drivers/net/ethernet/cisco/enic/enic.h
@@ -32,7 +32,7 @@
#define DRV_NAME "enic"
#define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Driver"
-#define DRV_VERSION "2.1.1.28"
+#define DRV_VERSION "2.1.1.31"
#define DRV_COPYRIGHT "Copyright 2008-2011 Cisco Systems, Inc"
#define ENIC_BARS_MAX 6
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index 2fd9db4b1be5..ab3f67f980d8 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -57,11 +57,13 @@
#define PCI_DEVICE_ID_CISCO_VIC_ENET 0x0043 /* ethernet vnic */
#define PCI_DEVICE_ID_CISCO_VIC_ENET_DYN 0x0044 /* enet dynamic vnic */
+#define PCI_DEVICE_ID_CISCO_VIC_ENET_VF 0x0071 /* enet SRIOV VF */
/* Supported devices */
static DEFINE_PCI_DEVICE_TABLE(enic_id_table) = {
{ PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET) },
{ PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET_DYN) },
+ { PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET_VF) },
{ 0, } /* end of table */
};
@@ -132,6 +134,11 @@ int enic_sriov_enabled(struct enic *enic)
return (enic->priv_flags & ENIC_SRIOV_ENABLED) ? 1 : 0;
}
+static int enic_is_sriov_vf(struct enic *enic)
+{
+ return enic->pdev->device == PCI_DEVICE_ID_CISCO_VIC_ENET_VF;
+}
+
int enic_is_valid_vf(struct enic *enic, int vf)
{
#ifdef CONFIG_PCI_IOV
@@ -437,7 +444,7 @@ static void enic_mtu_check(struct enic *enic)
if (mtu && mtu != enic->port_mtu) {
enic->port_mtu = mtu;
- if (enic_is_dynamic(enic)) {
+ if (enic_is_dynamic(enic) || enic_is_sriov_vf(enic)) {
mtu = max_t(int, ENIC_MIN_MTU,
min_t(int, ENIC_MAX_MTU, mtu));
if (mtu != netdev->mtu)
@@ -849,7 +856,7 @@ static int enic_set_mac_addr(struct net_device *netdev, char *addr)
{
struct enic *enic = netdev_priv(netdev);
- if (enic_is_dynamic(enic)) {
+ if (enic_is_dynamic(enic) || enic_is_sriov_vf(enic)) {
if (!is_valid_ether_addr(addr) && !is_zero_ether_addr(addr))
return -EADDRNOTAVAIL;
} else {
@@ -1608,7 +1615,7 @@ static int enic_open(struct net_device *netdev)
for (i = 0; i < enic->rq_count; i++)
vnic_rq_enable(&enic->rq[i]);
- if (!enic_is_dynamic(enic))
+ if (!enic_is_dynamic(enic) && !enic_is_sriov_vf(enic))
enic_dev_add_station_addr(enic);
enic_set_rx_mode(netdev);
@@ -1659,7 +1666,7 @@ static int enic_stop(struct net_device *netdev)
netif_carrier_off(netdev);
netif_tx_disable(netdev);
- if (!enic_is_dynamic(enic))
+ if (!enic_is_dynamic(enic) && !enic_is_sriov_vf(enic))
enic_dev_del_station_addr(enic);
for (i = 0; i < enic->wq_count; i++) {
@@ -1696,7 +1703,7 @@ static int enic_change_mtu(struct net_device *netdev, int new_mtu)
if (new_mtu < ENIC_MIN_MTU || new_mtu > ENIC_MAX_MTU)
return -EINVAL;
- if (enic_is_dynamic(enic))
+ if (enic_is_dynamic(enic) || enic_is_sriov_vf(enic))
return -EOPNOTSUPP;
if (running)
@@ -2263,10 +2270,10 @@ static int __devinit enic_probe(struct pci_dev *pdev,
int using_dac = 0;
unsigned int i;
int err;
- int num_pps = 1;
#ifdef CONFIG_PCI_IOV
int pos = 0;
#endif
+ int num_pps = 1;
/* Allocate net device structure and initialize. Private
* instance data is initialized to zero.
@@ -2376,14 +2383,14 @@ static int __devinit enic_probe(struct pci_dev *pdev,
num_pps = enic->num_vfs;
}
}
-
#endif
+
/* Allocate structure for port profiles */
enic->pp = kcalloc(num_pps, sizeof(*enic->pp), GFP_KERNEL);
if (!enic->pp) {
pr_err("port profile alloc failed, aborting\n");
err = -ENOMEM;
- goto err_out_disable_sriov;
+ goto err_out_disable_sriov_pp;
}
/* Issue device open to get device in known state
@@ -2392,7 +2399,7 @@ static int __devinit enic_probe(struct pci_dev *pdev,
err = enic_dev_open(enic);
if (err) {
dev_err(dev, "vNIC dev open failed, aborting\n");
- goto err_out_free_pp;
+ goto err_out_disable_sriov;
}
/* Setup devcmd lock
@@ -2426,7 +2433,7 @@ static int __devinit enic_probe(struct pci_dev *pdev,
* called later by an upper layer.
*/
- if (!enic_is_dynamic(enic)) {
+ if (!enic_is_dynamic(enic) && !enic_is_sriov_vf(enic)) {
err = vnic_dev_init(enic->vdev, 0);
if (err) {
dev_err(dev, "vNIC dev init failed, aborting\n");
@@ -2460,8 +2467,7 @@ static int __devinit enic_probe(struct pci_dev *pdev,
(void)enic_change_mtu(netdev, enic->port_mtu);
#ifdef CONFIG_PCI_IOV
- if (enic_is_dynamic(enic) && pdev->is_virtfn &&
- is_zero_ether_addr(enic->mac_addr))
+ if (enic_is_sriov_vf(enic) && is_zero_ether_addr(enic->mac_addr))
random_ether_addr(enic->mac_addr);
#endif
@@ -2474,7 +2480,7 @@ static int __devinit enic_probe(struct pci_dev *pdev,
enic->tx_coalesce_usecs = enic->config.intr_timer_usec;
enic->rx_coalesce_usecs = enic->tx_coalesce_usecs;
- if (enic_is_dynamic(enic))
+ if (enic_is_dynamic(enic) || enic_is_sriov_vf(enic))
netdev->netdev_ops = &enic_netdev_dynamic_ops;
else
netdev->netdev_ops = &enic_netdev_ops;
@@ -2516,17 +2522,17 @@ err_out_dev_deinit:
enic_dev_deinit(enic);
err_out_dev_close:
vnic_dev_close(enic->vdev);
-err_out_free_pp:
- kfree(enic->pp);
err_out_disable_sriov:
+ kfree(enic->pp);
+err_out_disable_sriov_pp:
#ifdef CONFIG_PCI_IOV
if (enic_sriov_enabled(enic)) {
pci_disable_sriov(pdev);
enic->priv_flags &= ~ENIC_SRIOV_ENABLED;
}
err_out_vnic_unregister:
- vnic_dev_unregister(enic->vdev);
#endif
+ vnic_dev_unregister(enic->vdev);
err_out_iounmap:
enic_iounmap(enic);
err_out_release_regions:
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index a6bcdb5cd2be..e703d64434f8 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -1786,8 +1786,7 @@ static void be_rx_queues_destroy(struct be_adapter *adapter)
static u32 be_num_rxqs_want(struct be_adapter *adapter)
{
if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) &&
- !sriov_enabled(adapter) && be_physfn(adapter) &&
- !be_is_mc(adapter)) {
+ !sriov_enabled(adapter) && be_physfn(adapter)) {
return 1 + MAX_RSS_QS; /* one default non-RSS queue */
} else {
dev_warn(&adapter->pdev->dev,
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index fb5579a3b19d..47f85c337cf7 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -25,6 +25,7 @@
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/netdevice.h>
diff --git a/drivers/net/ethernet/faraday/ftmac100.c b/drivers/net/ethernet/faraday/ftmac100.c
index a127cb2476c7..bb336a0959c9 100644
--- a/drivers/net/ethernet/faraday/ftmac100.c
+++ b/drivers/net/ethernet/faraday/ftmac100.c
@@ -25,6 +25,7 @@
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/mii.h>
#include <linux/module.h>
diff --git a/drivers/net/ethernet/intel/igb/Makefile b/drivers/net/ethernet/intel/igb/Makefile
index c6e4621b6262..6565c463185c 100644
--- a/drivers/net/ethernet/intel/igb/Makefile
+++ b/drivers/net/ethernet/intel/igb/Makefile
@@ -1,7 +1,7 @@
################################################################################
#
# Intel 82575 PCI-Express Ethernet Linux driver
-# Copyright(c) 1999 - 2011 Intel Corporation.
+# Copyright(c) 1999 - 2012 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,
diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c
index b8e20f037d0a..08bdc33715ee 100644
--- a/drivers/net/ethernet/intel/igb/e1000_82575.c
+++ b/drivers/net/ethernet/intel/igb/e1000_82575.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2011 Intel Corporation.
+ Copyright(c) 2007-2012 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,
diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.h b/drivers/net/ethernet/intel/igb/e1000_82575.h
index 08a757eb6608..b927d79ab536 100644
--- a/drivers/net/ethernet/intel/igb/e1000_82575.h
+++ b/drivers/net/ethernet/intel/igb/e1000_82575.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2011 Intel Corporation.
+ Copyright(c) 2007-2012 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,
diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h
index f5fc5725ea94..aed217449f0d 100644
--- a/drivers/net/ethernet/intel/igb/e1000_defines.h
+++ b/drivers/net/ethernet/intel/igb/e1000_defines.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2011 Intel Corporation.
+ Copyright(c) 2007-2012 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,
diff --git a/drivers/net/ethernet/intel/igb/e1000_hw.h b/drivers/net/ethernet/intel/igb/e1000_hw.h
index 4519a1367170..f67cbd3fa307 100644
--- a/drivers/net/ethernet/intel/igb/e1000_hw.h
+++ b/drivers/net/ethernet/intel/igb/e1000_hw.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2011 Intel Corporation.
+ Copyright(c) 2007-2012 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,
diff --git a/drivers/net/ethernet/intel/igb/e1000_mac.c b/drivers/net/ethernet/intel/igb/e1000_mac.c
index 73aac082c44d..f57338afd71f 100644
--- a/drivers/net/ethernet/intel/igb/e1000_mac.c
+++ b/drivers/net/ethernet/intel/igb/e1000_mac.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2011 Intel Corporation.
+ Copyright(c) 2007-2012 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,
@@ -151,7 +151,7 @@ void igb_clear_vfta_i350(struct e1000_hw *hw)
* Writes value at the given offset in the register array which stores
* the VLAN filter table.
**/
-void igb_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value)
+static void igb_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value)
{
int i;
diff --git a/drivers/net/ethernet/intel/igb/e1000_mac.h b/drivers/net/ethernet/intel/igb/e1000_mac.h
index e45996b4ea34..cbddc4e51e30 100644
--- a/drivers/net/ethernet/intel/igb/e1000_mac.h
+++ b/drivers/net/ethernet/intel/igb/e1000_mac.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2011 Intel Corporation.
+ Copyright(c) 2007-2012 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,
diff --git a/drivers/net/ethernet/intel/igb/e1000_mbx.c b/drivers/net/ethernet/intel/igb/e1000_mbx.c
index 469d95eaa154..5988b8958baf 100644
--- a/drivers/net/ethernet/intel/igb/e1000_mbx.c
+++ b/drivers/net/ethernet/intel/igb/e1000_mbx.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2011 Intel Corporation.
+ Copyright(c) 2007-2012 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,
diff --git a/drivers/net/ethernet/intel/igb/e1000_mbx.h b/drivers/net/ethernet/intel/igb/e1000_mbx.h
index eddb0f83dcea..dbcfa3d5caec 100644
--- a/drivers/net/ethernet/intel/igb/e1000_mbx.h
+++ b/drivers/net/ethernet/intel/igb/e1000_mbx.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2011 Intel Corporation.
+ Copyright(c) 2007-2012 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,
diff --git a/drivers/net/ethernet/intel/igb/e1000_nvm.c b/drivers/net/ethernet/intel/igb/e1000_nvm.c
index 40407124e722..fa2c6ba62139 100644
--- a/drivers/net/ethernet/intel/igb/e1000_nvm.c
+++ b/drivers/net/ethernet/intel/igb/e1000_nvm.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2011 Intel Corporation.
+ Copyright(c) 2007-2012 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,
diff --git a/drivers/net/ethernet/intel/igb/e1000_nvm.h b/drivers/net/ethernet/intel/igb/e1000_nvm.h
index a2a7ca9fa733..825b0228cac0 100644
--- a/drivers/net/ethernet/intel/igb/e1000_nvm.h
+++ b/drivers/net/ethernet/intel/igb/e1000_nvm.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2011 Intel Corporation.
+ Copyright(c) 2012 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,
diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.c b/drivers/net/ethernet/intel/igb/e1000_phy.c
index b17d7c20f817..789de5b83aad 100644
--- a/drivers/net/ethernet/intel/igb/e1000_phy.c
+++ b/drivers/net/ethernet/intel/igb/e1000_phy.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2011 Intel Corporation.
+ Copyright(c) 2007-2012 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,
diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.h b/drivers/net/ethernet/intel/igb/e1000_phy.h
index 8510797b9d81..4c32ac66ff39 100644
--- a/drivers/net/ethernet/intel/igb/e1000_phy.h
+++ b/drivers/net/ethernet/intel/igb/e1000_phy.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2011 Intel Corporation.
+ Copyright(c) 2007-2012 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,
diff --git a/drivers/net/ethernet/intel/igb/e1000_regs.h b/drivers/net/ethernet/intel/igb/e1000_regs.h
index 0a860bc1198e..ccdf36d503fd 100644
--- a/drivers/net/ethernet/intel/igb/e1000_regs.h
+++ b/drivers/net/ethernet/intel/igb/e1000_regs.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2011 Intel Corporation.
+ Copyright(c) 2007-2012 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,
diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
index 3d12e67eebb4..8e33bdd33eea 100644
--- a/drivers/net/ethernet/intel/igb/igb.h
+++ b/drivers/net/ethernet/intel/igb/igb.h
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2011 Intel Corporation.
+ Copyright(c) 2007-2012 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,
diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
index 7998bf4d5946..aa399a8a8f0d 100644
--- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
+++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2011 Intel Corporation.
+ Copyright(c) 2007-2012 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,
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 01e5e89ef959..e91d73c8aa4e 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -1,7 +1,7 @@
/*******************************************************************************
Intel(R) Gigabit Ethernet Linux driver
- Copyright(c) 2007-2011 Intel Corporation.
+ Copyright(c) 2007-2012 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,
@@ -68,7 +68,7 @@ char igb_driver_name[] = "igb";
char igb_driver_version[] = DRV_VERSION;
static const char igb_driver_string[] =
"Intel(R) Gigabit Ethernet Network Driver";
-static const char igb_copyright[] = "Copyright (c) 2007-2011 Intel Corporation.";
+static const char igb_copyright[] = "Copyright (c) 2007-2012 Intel Corporation.";
static const struct e1000_info *igb_info_tbl[] = {
[board_82575] = &e1000_82575_info,
@@ -4003,8 +4003,8 @@ set_itr_now:
}
}
-void igb_tx_ctxtdesc(struct igb_ring *tx_ring, u32 vlan_macip_lens,
- u32 type_tucmd, u32 mss_l4len_idx)
+static void igb_tx_ctxtdesc(struct igb_ring *tx_ring, u32 vlan_macip_lens,
+ u32 type_tucmd, u32 mss_l4len_idx)
{
struct e1000_adv_tx_context_desc *context_desc;
u16 i = tx_ring->next_to_use;
@@ -5623,7 +5623,7 @@ static irqreturn_t igb_intr(int irq, void *data)
return IRQ_HANDLED;
}
-void igb_ring_irq_enable(struct igb_q_vector *q_vector)
+static void igb_ring_irq_enable(struct igb_q_vector *q_vector)
{
struct igb_adapter *adapter = q_vector->adapter;
struct e1000_hw *hw = &adapter->hw;
diff --git a/drivers/net/ethernet/intel/igbvf/ethtool.c b/drivers/net/ethernet/intel/igbvf/ethtool.c
index 7b600a1f6366..2dba53446064 100644
--- a/drivers/net/ethernet/intel/igbvf/ethtool.c
+++ b/drivers/net/ethernet/intel/igbvf/ethtool.c
@@ -468,6 +468,5 @@ static const struct ethtool_ops igbvf_ethtool_ops = {
void igbvf_set_ethtool_ops(struct net_device *netdev)
{
- /* have to "undeclare" const on this struct to remove warnings */
- SET_ETHTOOL_OPS(netdev, (struct ethtool_ops *)&igbvf_ethtool_ops);
+ SET_ETHTOOL_OPS(netdev, &igbvf_ethtool_ops);
}
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
index fd3da3076c2f..a4b20c865759 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -1194,11 +1194,6 @@ static int igbvf_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
struct igbvf_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- igbvf_irq_disable(adapter);
-
- if (!test_bit(__IGBVF_DOWN, &adapter->state))
- igbvf_irq_enable(adapter);
-
if (hw->mac.ops.set_vfta(hw, vid, false)) {
dev_err(&adapter->pdev->dev,
"Failed to remove vlan id %d\n", vid);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
index 802bfa0f62cc..775602ef90e5 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
@@ -161,19 +161,19 @@
/* Receive DMA Registers */
#define IXGBE_RDBAL(_i) (((_i) < 64) ? (0x01000 + ((_i) * 0x40)) : \
- (0x0D000 + ((_i - 64) * 0x40)))
+ (0x0D000 + (((_i) - 64) * 0x40)))
#define IXGBE_RDBAH(_i) (((_i) < 64) ? (0x01004 + ((_i) * 0x40)) : \
- (0x0D004 + ((_i - 64) * 0x40)))
+ (0x0D004 + (((_i) - 64) * 0x40)))
#define IXGBE_RDLEN(_i) (((_i) < 64) ? (0x01008 + ((_i) * 0x40)) : \
- (0x0D008 + ((_i - 64) * 0x40)))
+ (0x0D008 + (((_i) - 64) * 0x40)))
#define IXGBE_RDH(_i) (((_i) < 64) ? (0x01010 + ((_i) * 0x40)) : \
- (0x0D010 + ((_i - 64) * 0x40)))
+ (0x0D010 + (((_i) - 64) * 0x40)))
#define IXGBE_RDT(_i) (((_i) < 64) ? (0x01018 + ((_i) * 0x40)) : \
- (0x0D018 + ((_i - 64) * 0x40)))
+ (0x0D018 + (((_i) - 64) * 0x40)))
#define IXGBE_RXDCTL(_i) (((_i) < 64) ? (0x01028 + ((_i) * 0x40)) : \
- (0x0D028 + ((_i - 64) * 0x40)))
+ (0x0D028 + (((_i) - 64) * 0x40)))
#define IXGBE_RSCCTL(_i) (((_i) < 64) ? (0x0102C + ((_i) * 0x40)) : \
- (0x0D02C + ((_i - 64) * 0x40)))
+ (0x0D02C + (((_i) - 64) * 0x40)))
#define IXGBE_RSCDBU 0x03028
#define IXGBE_RDDCC 0x02F20
#define IXGBE_RXMEMWRAP 0x03190
@@ -186,7 +186,7 @@
*/
#define IXGBE_SRRCTL(_i) (((_i) <= 15) ? (0x02100 + ((_i) * 4)) : \
(((_i) < 64) ? (0x01014 + ((_i) * 0x40)) : \
- (0x0D014 + ((_i - 64) * 0x40))))
+ (0x0D014 + (((_i) - 64) * 0x40))))
/*
* Rx DCA Control Register:
* 00-15 : 0x02200 + n*4
@@ -195,7 +195,7 @@
*/
#define IXGBE_DCA_RXCTRL(_i) (((_i) <= 15) ? (0x02200 + ((_i) * 4)) : \
(((_i) < 64) ? (0x0100C + ((_i) * 0x40)) : \
- (0x0D00C + ((_i - 64) * 0x40))))
+ (0x0D00C + (((_i) - 64) * 0x40))))
#define IXGBE_RDRXCTL 0x02F00
#define IXGBE_RXPBSIZE(_i) (0x03C00 + ((_i) * 4))
/* 8 of these 0x03C00 - 0x03C1C */
@@ -344,9 +344,9 @@
#define IXGBE_WUPL 0x05900
#define IXGBE_WUPM 0x05A00 /* wake up pkt memory 0x5A00-0x5A7C */
-#define IXGBE_FHFT(_n) (0x09000 + (_n * 0x100)) /* Flex host filter table */
-#define IXGBE_FHFT_EXT(_n) (0x09800 + (_n * 0x100)) /* Ext Flexible Host
- * Filter Table */
+#define IXGBE_FHFT(_n) (0x09000 + ((_n) * 0x100)) /* Flex host filter table */
+#define IXGBE_FHFT_EXT(_n) (0x09800 + ((_n) * 0x100)) /* Ext Flexible Host
+ * Filter Table */
#define IXGBE_FLEXIBLE_FILTER_COUNT_MAX 4
#define IXGBE_EXT_FLEXIBLE_FILTER_COUNT_MAX 2
@@ -1485,7 +1485,7 @@ enum {
#define IXGBE_LED_BLINK_BASE 0x00000080
#define IXGBE_LED_MODE_MASK_BASE 0x0000000F
#define IXGBE_LED_OFFSET(_base, _i) (_base << (8 * (_i)))
-#define IXGBE_LED_MODE_SHIFT(_i) (8*(_i))
+#define IXGBE_LED_MODE_SHIFT(_i) (8 * (_i))
#define IXGBE_LED_IVRT(_i) IXGBE_LED_OFFSET(IXGBE_LED_IVRT_BASE, _i)
#define IXGBE_LED_BLINK(_i) IXGBE_LED_OFFSET(IXGBE_LED_BLINK_BASE, _i)
#define IXGBE_LED_MODE_MASK(_i) IXGBE_LED_OFFSET(IXGBE_LED_MODE_MASK_BASE, _i)
@@ -2068,9 +2068,9 @@ enum {
/* SR-IOV specific macros */
#define IXGBE_MBVFICR_INDEX(vf_number) (vf_number >> 4)
-#define IXGBE_MBVFICR(_i) (0x00710 + (_i * 4))
-#define IXGBE_VFLRE(_i) (((_i & 1) ? 0x001C0 : 0x00600))
-#define IXGBE_VFLREC(_i) (0x00700 + (_i * 4))
+#define IXGBE_MBVFICR(_i) (0x00710 + ((_i) * 4))
+#define IXGBE_VFLRE(_i) ((((_i) & 1) ? 0x001C0 : 0x00600))
+#define IXGBE_VFLREC(_i) (0x00700 + ((_i) * 4))
enum ixgbe_fdir_pballoc_type {
IXGBE_FDIR_PBALLOC_NONE = 0,
diff --git a/drivers/net/ethernet/intel/ixgbevf/ethtool.c b/drivers/net/ethernet/intel/ixgbevf/ethtool.c
index dc8e6511c640..c85700318147 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ethtool.c
@@ -56,7 +56,8 @@ struct ixgbe_stats {
offsetof(struct ixgbevf_adapter, m), \
offsetof(struct ixgbevf_adapter, b), \
offsetof(struct ixgbevf_adapter, r)
-static struct ixgbe_stats ixgbe_gstrings_stats[] = {
+
+static const struct ixgbe_stats ixgbe_gstrings_stats[] = {
{"rx_packets", IXGBEVF_STAT(stats.vfgprc, stats.base_vfgprc,
stats.saved_reset_vfgprc)},
{"tx_packets", IXGBEVF_STAT(stats.vfgptc, stats.base_vfgptc,
@@ -671,7 +672,7 @@ static int ixgbevf_nway_reset(struct net_device *netdev)
return 0;
}
-static struct ethtool_ops ixgbevf_ethtool_ops = {
+static const struct ethtool_ops ixgbevf_ethtool_ops = {
.get_settings = ixgbevf_get_settings,
.get_drvinfo = ixgbevf_get_drvinfo,
.get_regs_len = ixgbevf_get_regs_len,
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
index e6c9d1a927a9..9075c1d61039 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
@@ -279,12 +279,12 @@ enum ixgbevf_boards {
board_X540_vf,
};
-extern struct ixgbevf_info ixgbevf_82599_vf_info;
-extern struct ixgbevf_info ixgbevf_X540_vf_info;
-extern struct ixgbe_mbx_operations ixgbevf_mbx_ops;
+extern const struct ixgbevf_info ixgbevf_82599_vf_info;
+extern const struct ixgbevf_info ixgbevf_X540_vf_info;
+extern const struct ixgbe_mbx_operations ixgbevf_mbx_ops;
/* needed by ethtool.c */
-extern char ixgbevf_driver_name[];
+extern const char ixgbevf_driver_name[];
extern const char ixgbevf_driver_version[];
extern int ixgbevf_up(struct ixgbevf_adapter *adapter);
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index 891162d1610c..bed411bada21 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -53,7 +53,7 @@
#include "ixgbevf.h"
-char ixgbevf_driver_name[] = "ixgbevf";
+const char ixgbevf_driver_name[] = "ixgbevf";
static const char ixgbevf_driver_string[] =
"Intel(R) 10 Gigabit PCI Express Virtual Function Network Driver";
@@ -917,31 +917,34 @@ static irqreturn_t ixgbevf_msix_mbx(int irq, void *data)
struct ixgbe_hw *hw = &adapter->hw;
u32 eicr;
u32 msg;
+ bool got_ack = false;
eicr = IXGBE_READ_REG(hw, IXGBE_VTEICS);
IXGBE_WRITE_REG(hw, IXGBE_VTEICR, eicr);
- if (!hw->mbx.ops.check_for_ack(hw)) {
- /*
- * checking for the ack clears the PFACK bit. Place
- * it back in the v2p_mailbox cache so that anyone
- * polling for an ack will not miss it. Also
- * avoid the read below because the code to read
- * the mailbox will also clear the ack bit. This was
- * causing lost acks. Just cache the bit and exit
- * the IRQ handler.
- */
- hw->mbx.v2p_mailbox |= IXGBE_VFMAILBOX_PFACK;
- goto out;
- }
+ if (!hw->mbx.ops.check_for_ack(hw))
+ got_ack = true;
- /* Not an ack interrupt, go ahead and read the message */
- hw->mbx.ops.read(hw, &msg, 1);
+ if (!hw->mbx.ops.check_for_msg(hw)) {
+ hw->mbx.ops.read(hw, &msg, 1);
- if ((msg & IXGBE_MBVFICR_VFREQ_MASK) == IXGBE_PF_CONTROL_MSG)
- mod_timer(&adapter->watchdog_timer,
- round_jiffies(jiffies + 1));
+ if ((msg & IXGBE_MBVFICR_VFREQ_MASK) == IXGBE_PF_CONTROL_MSG)
+ mod_timer(&adapter->watchdog_timer,
+ round_jiffies(jiffies + 1));
+ if (msg & IXGBE_VT_MSGTYPE_NACK)
+ pr_warn("Last Request of type %2.2x to PF Nacked\n",
+ msg & 0xFF);
+ goto out;
+ }
+
+ /*
+ * checking for the ack clears the PFACK bit. Place
+ * it back in the v2p_mailbox cache so that anyone
+ * polling for an ack will not miss it
+ */
+ if (got_ack)
+ hw->mbx.v2p_mailbox |= IXGBE_VFMAILBOX_PFACK;
out:
return IRQ_HANDLED;
}
diff --git a/drivers/net/ethernet/intel/ixgbevf/mbx.c b/drivers/net/ethernet/intel/ixgbevf/mbx.c
index 930fa83f2568..13532d9ba72d 100644
--- a/drivers/net/ethernet/intel/ixgbevf/mbx.c
+++ b/drivers/net/ethernet/intel/ixgbevf/mbx.c
@@ -26,6 +26,7 @@
*******************************************************************************/
#include "mbx.h"
+#include "ixgbevf.h"
/**
* ixgbevf_poll_for_msg - Wait for message notification
@@ -328,7 +329,7 @@ static s32 ixgbevf_init_mbx_params_vf(struct ixgbe_hw *hw)
return 0;
}
-struct ixgbe_mbx_operations ixgbevf_mbx_ops = {
+const struct ixgbe_mbx_operations ixgbevf_mbx_ops = {
.init_params = ixgbevf_init_mbx_params_vf,
.read = ixgbevf_read_mbx_vf,
.write = ixgbevf_write_mbx_vf,
diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.c b/drivers/net/ethernet/intel/ixgbevf/vf.c
index 21533e300367..d0138d7a31a1 100644
--- a/drivers/net/ethernet/intel/ixgbevf/vf.c
+++ b/drivers/net/ethernet/intel/ixgbevf/vf.c
@@ -26,6 +26,7 @@
*******************************************************************************/
#include "vf.h"
+#include "ixgbevf.h"
/**
* ixgbevf_start_hw_vf - Prepare hardware for Tx/Rx
@@ -401,7 +402,7 @@ static s32 ixgbevf_check_mac_link_vf(struct ixgbe_hw *hw,
return 0;
}
-static struct ixgbe_mac_operations ixgbevf_mac_ops = {
+static const struct ixgbe_mac_operations ixgbevf_mac_ops = {
.init_hw = ixgbevf_init_hw_vf,
.reset_hw = ixgbevf_reset_hw_vf,
.start_hw = ixgbevf_start_hw_vf,
@@ -415,12 +416,12 @@ static struct ixgbe_mac_operations ixgbevf_mac_ops = {
.set_vfta = ixgbevf_set_vfta_vf,
};
-struct ixgbevf_info ixgbevf_82599_vf_info = {
+const struct ixgbevf_info ixgbevf_82599_vf_info = {
.mac = ixgbe_mac_82599_vf,
.mac_ops = &ixgbevf_mac_ops,
};
-struct ixgbevf_info ixgbevf_X540_vf_info = {
+const struct ixgbevf_info ixgbevf_X540_vf_info = {
.mac = ixgbe_mac_X540_vf,
.mac_ops = &ixgbevf_mac_ops,
};
diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.h b/drivers/net/ethernet/intel/ixgbevf/vf.h
index 10306b492ee6..d556619a9212 100644
--- a/drivers/net/ethernet/intel/ixgbevf/vf.h
+++ b/drivers/net/ethernet/intel/ixgbevf/vf.h
@@ -167,7 +167,7 @@ struct ixgbevf_hw_stats {
struct ixgbevf_info {
enum ixgbe_mac_type mac;
- struct ixgbe_mac_operations *mac_ops;
+ const struct ixgbe_mac_operations *mac_ops;
};
#endif /* __IXGBE_VF_H__ */
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index 9c049d2cb97d..9edecfa1f0f4 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -136,6 +136,8 @@ static char mv643xx_eth_driver_version[] = "1.4";
#define INT_MASK 0x0068
#define INT_MASK_EXT 0x006c
#define TX_FIFO_URGENT_THRESHOLD 0x0074
+#define RX_DISCARD_FRAME_CNT 0x0084
+#define RX_OVERRUN_FRAME_CNT 0x0088
#define TXQ_FIX_PRIO_CONF_MOVED 0x00dc
#define TX_BW_RATE_MOVED 0x00e0
#define TX_BW_MTU_MOVED 0x00e8
@@ -334,6 +336,9 @@ struct mib_counters {
u32 bad_crc_event;
u32 collision;
u32 late_collision;
+ /* Non MIB hardware counters */
+ u32 rx_discard;
+ u32 rx_overrun;
};
struct lro_counters {
@@ -1225,6 +1230,10 @@ static void mib_counters_clear(struct mv643xx_eth_private *mp)
for (i = 0; i < 0x80; i += 4)
mib_read(mp, i);
+
+ /* Clear non MIB hw counters also */
+ rdlp(mp, RX_DISCARD_FRAME_CNT);
+ rdlp(mp, RX_OVERRUN_FRAME_CNT);
}
static void mib_counters_update(struct mv643xx_eth_private *mp)
@@ -1262,6 +1271,9 @@ static void mib_counters_update(struct mv643xx_eth_private *mp)
p->bad_crc_event += mib_read(mp, 0x74);
p->collision += mib_read(mp, 0x78);
p->late_collision += mib_read(mp, 0x7c);
+ /* Non MIB hardware counters */
+ p->rx_discard += rdlp(mp, RX_DISCARD_FRAME_CNT);
+ p->rx_overrun += rdlp(mp, RX_OVERRUN_FRAME_CNT);
spin_unlock_bh(&mp->mib_counters_lock);
mod_timer(&mp->mib_counters_timer, jiffies + 30 * HZ);
@@ -1413,6 +1425,8 @@ static const struct mv643xx_eth_stats mv643xx_eth_stats[] = {
MIBSTAT(bad_crc_event),
MIBSTAT(collision),
MIBSTAT(late_collision),
+ MIBSTAT(rx_discard),
+ MIBSTAT(rx_overrun),
LROSTAT(lro_aggregated),
LROSTAT(lro_flushed),
LROSTAT(lro_no_desc),
diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c
index 18a87a57fc0a..edb9bda55d55 100644
--- a/drivers/net/ethernet/marvell/skge.c
+++ b/drivers/net/ethernet/marvell/skge.c
@@ -931,17 +931,20 @@ static int skge_ring_alloc(struct skge_ring *ring, void *vaddr, u32 base)
}
/* Allocate and setup a new buffer for receiving */
-static void skge_rx_setup(struct skge_port *skge, struct skge_element *e,
- struct sk_buff *skb, unsigned int bufsize)
+static int skge_rx_setup(struct pci_dev *pdev,
+ struct skge_element *e,
+ struct sk_buff *skb, unsigned int bufsize)
{
struct skge_rx_desc *rd = e->desc;
- u64 map;
+ dma_addr_t map;
- map = pci_map_single(skge->hw->pdev, skb->data, bufsize,
+ map = pci_map_single(pdev, skb->data, bufsize,
PCI_DMA_FROMDEVICE);
+ if (pci_dma_mapping_error(pdev, map))
+ goto mapping_error;
- rd->dma_lo = map;
- rd->dma_hi = map >> 32;
+ rd->dma_lo = lower_32_bits(map);
+ rd->dma_hi = upper_32_bits(map);
e->skb = skb;
rd->csum1_start = ETH_HLEN;
rd->csum2_start = ETH_HLEN;
@@ -953,6 +956,13 @@ static void skge_rx_setup(struct skge_port *skge, struct skge_element *e,
rd->control = BMU_OWN | BMU_STF | BMU_IRQ_EOF | BMU_TCP_CHECK | bufsize;
dma_unmap_addr_set(e, mapaddr, map);
dma_unmap_len_set(e, maplen, bufsize);
+ return 0;
+
+mapping_error:
+ if (net_ratelimit())
+ dev_warn(&pdev->dev, "%s: rx mapping error\n",
+ skb->dev->name);
+ return -EIO;
}
/* Resume receiving using existing skb,
@@ -1014,7 +1024,11 @@ static int skge_rx_fill(struct net_device *dev)
return -ENOMEM;
skb_reserve(skb, NET_IP_ALIGN);
- skge_rx_setup(skge, e, skb, skge->rx_buf_size);
+ if (skge_rx_setup(skge->hw->pdev, e, skb, skge->rx_buf_size)) {
+ kfree_skb(skb);
+ return -ENOMEM;
+ }
+
} while ((e = e->next) != ring->start);
ring->to_clean = ring->start;
@@ -2576,6 +2590,7 @@ static int skge_up(struct net_device *dev)
}
/* Initialize MAC */
+ netif_carrier_off(dev);
spin_lock_bh(&hw->phy_lock);
if (is_genesis(hw))
genesis_mac_init(hw, port);
@@ -2728,7 +2743,7 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb,
struct skge_tx_desc *td;
int i;
u32 control, len;
- u64 map;
+ dma_addr_t map;
if (skb_padto(skb, ETH_ZLEN))
return NETDEV_TX_OK;
@@ -2742,11 +2757,14 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb,
e->skb = skb;
len = skb_headlen(skb);
map = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE);
+ if (pci_dma_mapping_error(hw->pdev, map))
+ goto mapping_error;
+
dma_unmap_addr_set(e, mapaddr, map);
dma_unmap_len_set(e, maplen, len);
- td->dma_lo = map;
- td->dma_hi = map >> 32;
+ td->dma_lo = lower_32_bits(map);
+ td->dma_hi = upper_32_bits(map);
if (skb->ip_summed == CHECKSUM_PARTIAL) {
const int offset = skb_checksum_start_offset(skb);
@@ -2777,14 +2795,16 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb,
map = skb_frag_dma_map(&hw->pdev->dev, frag, 0,
skb_frag_size(frag), DMA_TO_DEVICE);
+ if (dma_mapping_error(&hw->pdev->dev, map))
+ goto mapping_unwind;
e = e->next;
e->skb = skb;
tf = e->desc;
BUG_ON(tf->control & BMU_OWN);
- tf->dma_lo = map;
- tf->dma_hi = (u64) map >> 32;
+ tf->dma_lo = lower_32_bits(map);
+ tf->dma_hi = upper_32_bits(map);
dma_unmap_addr_set(e, mapaddr, map);
dma_unmap_len_set(e, maplen, skb_frag_size(frag));
@@ -2797,6 +2817,8 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb,
td->control = BMU_OWN | BMU_SW | BMU_STF | control | len;
wmb();
+ netdev_sent_queue(dev, skb->len);
+
skge_write8(hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_START);
netif_printk(skge, tx_queued, KERN_DEBUG, skge->netdev,
@@ -2812,15 +2834,35 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb,
}
return NETDEV_TX_OK;
+
+mapping_unwind:
+ /* unroll any pages that were already mapped. */
+ if (e != skge->tx_ring.to_use) {
+ struct skge_element *u;
+
+ for (u = skge->tx_ring.to_use->next; u != e; u = u->next)
+ pci_unmap_page(hw->pdev, dma_unmap_addr(u, mapaddr),
+ dma_unmap_len(u, maplen),
+ PCI_DMA_TODEVICE);
+ e = skge->tx_ring.to_use;
+ }
+ /* undo the mapping for the skb header */
+ pci_unmap_single(hw->pdev, dma_unmap_addr(e, mapaddr),
+ dma_unmap_len(e, maplen),
+ PCI_DMA_TODEVICE);
+mapping_error:
+ /* mapping error causes error message and packet to be discarded. */
+ if (net_ratelimit())
+ dev_warn(&hw->pdev->dev, "%s: tx mapping error\n", dev->name);
+ dev_kfree_skb(skb);
+ return NETDEV_TX_OK;
}
/* Free resources associated with this reing element */
-static void skge_tx_free(struct skge_port *skge, struct skge_element *e,
- u32 control)
+static inline void skge_tx_unmap(struct pci_dev *pdev, struct skge_element *e,
+ u32 control)
{
- struct pci_dev *pdev = skge->hw->pdev;
-
/* skb header vs. fragment */
if (control & BMU_STF)
pci_unmap_single(pdev, dma_unmap_addr(e, mapaddr),
@@ -2830,13 +2872,6 @@ static void skge_tx_free(struct skge_port *skge, struct skge_element *e,
pci_unmap_page(pdev, dma_unmap_addr(e, mapaddr),
dma_unmap_len(e, maplen),
PCI_DMA_TODEVICE);
-
- if (control & BMU_EOF) {
- netif_printk(skge, tx_done, KERN_DEBUG, skge->netdev,
- "tx done slot %td\n", e - skge->tx_ring.start);
-
- dev_kfree_skb(e->skb);
- }
}
/* Free all buffers in transmit ring */
@@ -2847,10 +2882,15 @@ static void skge_tx_clean(struct net_device *dev)
for (e = skge->tx_ring.to_clean; e != skge->tx_ring.to_use; e = e->next) {
struct skge_tx_desc *td = e->desc;
- skge_tx_free(skge, e, td->control);
+
+ skge_tx_unmap(skge->hw->pdev, e, td->control);
+
+ if (td->control & BMU_EOF)
+ dev_kfree_skb(e->skb);
td->control = 0;
}
+ netdev_reset_queue(dev);
skge->tx_ring.to_clean = e;
}
@@ -3059,13 +3099,17 @@ static struct sk_buff *skge_rx_get(struct net_device *dev,
if (!nskb)
goto resubmit;
+ if (unlikely(skge_rx_setup(skge->hw->pdev, e, nskb, skge->rx_buf_size))) {
+ dev_kfree_skb(nskb);
+ goto resubmit;
+ }
+
pci_unmap_single(skge->hw->pdev,
dma_unmap_addr(e, mapaddr),
dma_unmap_len(e, maplen),
PCI_DMA_FROMDEVICE);
skb = e->skb;
prefetch(skb->data);
- skge_rx_setup(skge, e, nskb, skge->rx_buf_size);
}
skb_put(skb, len);
@@ -3111,6 +3155,7 @@ static void skge_tx_done(struct net_device *dev)
struct skge_port *skge = netdev_priv(dev);
struct skge_ring *ring = &skge->tx_ring;
struct skge_element *e;
+ unsigned int bytes_compl = 0, pkts_compl = 0;
skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F);
@@ -3120,8 +3165,20 @@ static void skge_tx_done(struct net_device *dev)
if (control & BMU_OWN)
break;
- skge_tx_free(skge, e, control);
+ skge_tx_unmap(skge->hw->pdev, e, control);
+
+ if (control & BMU_EOF) {
+ netif_printk(skge, tx_done, KERN_DEBUG, skge->netdev,
+ "tx done slot %td\n",
+ e - skge->tx_ring.start);
+
+ pkts_compl++;
+ bytes_compl += e->skb->len;
+
+ dev_kfree_skb(e->skb);
+ }
}
+ netdev_completed_queue(dev, pkts_compl, bytes_compl);
skge->tx_ring.to_clean = e;
/* Can run lockless until we need to synchronize to restart queue. */
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c
index 978f593094c0..405e6ac3faf6 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c
@@ -1247,6 +1247,7 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd,
u32 reply;
u32 slave_status = 0;
u8 is_going_down = 0;
+ int i;
slave_state[slave].comm_toggle ^= 1;
reply = (u32) slave_state[slave].comm_toggle << 31;
@@ -1258,6 +1259,10 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd,
if (cmd == MLX4_COMM_CMD_RESET) {
mlx4_warn(dev, "Received reset from slave:%d\n", slave);
slave_state[slave].active = false;
+ for (i = 0; i < MLX4_EVENT_TYPES_NUM; ++i) {
+ slave_state[slave].event_eq[i].eqn = -1;
+ slave_state[slave].event_eq[i].token = 0;
+ }
/*check if we are in the middle of FLR process,
if so return "retry" status to the slave*/
if (MLX4_COMM_CMD_FLR == slave_state[slave].last_cmd) {
@@ -1452,7 +1457,7 @@ int mlx4_multi_func_init(struct mlx4_dev *dev)
{
struct mlx4_priv *priv = mlx4_priv(dev);
struct mlx4_slave_state *s_state;
- int i, err, port;
+ int i, j, err, port;
priv->mfunc.vhcr = dma_alloc_coherent(&(dev->pdev->dev), PAGE_SIZE,
&priv->mfunc.vhcr_dma,
@@ -1485,6 +1490,8 @@ int mlx4_multi_func_init(struct mlx4_dev *dev)
for (i = 0; i < dev->num_slaves; ++i) {
s_state = &priv->mfunc.master.slave_state[i];
s_state->last_cmd = MLX4_COMM_CMD_RESET;
+ for (j = 0; j < MLX4_EVENT_TYPES_NUM; ++j)
+ s_state->event_eq[j].eqn = -1;
__raw_writel((__force u32) 0,
&priv->mfunc.comm[i].slave_write);
__raw_writel((__force u32) 0,
diff --git a/drivers/net/ethernet/mellanox/mlx4/cq.c b/drivers/net/ethernet/mellanox/mlx4/cq.c
index 475f9d6af955..7e64033d7de3 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cq.c
@@ -96,7 +96,7 @@ void mlx4_cq_event(struct mlx4_dev *dev, u32 cqn, int event_type)
static int mlx4_SW2HW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
int cq_num)
{
- return mlx4_cmd(dev, mailbox->dma | dev->caps.function, cq_num, 0,
+ return mlx4_cmd(dev, mailbox->dma, cq_num, 0,
MLX4_CMD_SW2HW_CQ, MLX4_CMD_TIME_CLASS_A,
MLX4_CMD_WRAPPED);
}
@@ -111,7 +111,7 @@ static int mlx4_MODIFY_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox
static int mlx4_HW2SW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
int cq_num)
{
- return mlx4_cmd_box(dev, dev->caps.function, mailbox ? mailbox->dma : 0,
+ return mlx4_cmd_box(dev, 0, mailbox ? mailbox->dma : 0,
cq_num, mailbox ? 0 : 1, MLX4_CMD_HW2SW_CQ,
MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
}
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
index 7dbc6a230779..70346fd7f9c4 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
@@ -183,10 +183,11 @@ static int mlx4_en_set_wol(struct net_device *netdev,
static int mlx4_en_get_sset_count(struct net_device *dev, int sset)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
+ int bit_count = hweight64(priv->stats_bitmap);
switch (sset) {
case ETH_SS_STATS:
- return NUM_ALL_STATS +
+ return (priv->stats_bitmap ? bit_count : NUM_ALL_STATS) +
(priv->tx_ring_num + priv->rx_ring_num) * 2;
case ETH_SS_TEST:
return MLX4_EN_NUM_SELF_TEST - !(priv->mdev->dev->caps.flags
@@ -201,14 +202,34 @@ static void mlx4_en_get_ethtool_stats(struct net_device *dev,
{
struct mlx4_en_priv *priv = netdev_priv(dev);
int index = 0;
- int i;
+ int i, j = 0;
spin_lock_bh(&priv->stats_lock);
- for (i = 0; i < NUM_MAIN_STATS; i++)
- data[index++] = ((unsigned long *) &priv->stats)[i];
- for (i = 0; i < NUM_PORT_STATS; i++)
- data[index++] = ((unsigned long *) &priv->port_stats)[i];
+ if (!(priv->stats_bitmap)) {
+ for (i = 0; i < NUM_MAIN_STATS; i++)
+ data[index++] =
+ ((unsigned long *) &priv->stats)[i];
+ for (i = 0; i < NUM_PORT_STATS; i++)
+ data[index++] =
+ ((unsigned long *) &priv->port_stats)[i];
+ for (i = 0; i < NUM_PKT_STATS; i++)
+ data[index++] =
+ ((unsigned long *) &priv->pkstats)[i];
+ } else {
+ for (i = 0; i < NUM_MAIN_STATS; i++) {
+ if ((priv->stats_bitmap >> j) & 1)
+ data[index++] =
+ ((unsigned long *) &priv->stats)[i];
+ j++;
+ }
+ for (i = 0; i < NUM_PORT_STATS; i++) {
+ if ((priv->stats_bitmap >> j) & 1)
+ data[index++] =
+ ((unsigned long *) &priv->port_stats)[i];
+ j++;
+ }
+ }
for (i = 0; i < priv->tx_ring_num; i++) {
data[index++] = priv->tx_ring[i].packets;
data[index++] = priv->tx_ring[i].bytes;
@@ -217,8 +238,6 @@ static void mlx4_en_get_ethtool_stats(struct net_device *dev,
data[index++] = priv->rx_ring[i].packets;
data[index++] = priv->rx_ring[i].bytes;
}
- for (i = 0; i < NUM_PKT_STATS; i++)
- data[index++] = ((unsigned long *) &priv->pkstats)[i];
spin_unlock_bh(&priv->stats_lock);
}
@@ -247,11 +266,29 @@ static void mlx4_en_get_strings(struct net_device *dev,
case ETH_SS_STATS:
/* Add main counters */
- for (i = 0; i < NUM_MAIN_STATS; i++)
- strcpy(data + (index++) * ETH_GSTRING_LEN, main_strings[i]);
- for (i = 0; i< NUM_PORT_STATS; i++)
- strcpy(data + (index++) * ETH_GSTRING_LEN,
- main_strings[i + NUM_MAIN_STATS]);
+ if (!priv->stats_bitmap) {
+ for (i = 0; i < NUM_MAIN_STATS; i++)
+ strcpy(data + (index++) * ETH_GSTRING_LEN,
+ main_strings[i]);
+ for (i = 0; i < NUM_PORT_STATS; i++)
+ strcpy(data + (index++) * ETH_GSTRING_LEN,
+ main_strings[i +
+ NUM_MAIN_STATS]);
+ for (i = 0; i < NUM_PKT_STATS; i++)
+ strcpy(data + (index++) * ETH_GSTRING_LEN,
+ main_strings[i +
+ NUM_MAIN_STATS +
+ NUM_PORT_STATS]);
+ } else
+ for (i = 0; i < NUM_MAIN_STATS + NUM_PORT_STATS; i++) {
+ if ((priv->stats_bitmap >> i) & 1) {
+ strcpy(data +
+ (index++) * ETH_GSTRING_LEN,
+ main_strings[i]);
+ }
+ if (!(priv->stats_bitmap >> i))
+ break;
+ }
for (i = 0; i < priv->tx_ring_num; i++) {
sprintf(data + (index++) * ETH_GSTRING_LEN,
"tx%d_packets", i);
@@ -264,9 +301,6 @@ static void mlx4_en_get_strings(struct net_device *dev,
sprintf(data + (index++) * ETH_GSTRING_LEN,
"rx%d_bytes", i);
}
- for (i = 0; i< NUM_PKT_STATS; i++)
- strcpy(data + (index++) * ETH_GSTRING_LEN,
- main_strings[i + NUM_MAIN_STATS + NUM_PORT_STATS]);
break;
}
}
@@ -479,6 +513,95 @@ static void mlx4_en_get_ringparam(struct net_device *dev,
param->tx_pending = priv->tx_ring[0].size;
}
+static u32 mlx4_en_get_rxfh_indir_size(struct net_device *dev)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+
+ return priv->rx_ring_num;
+}
+
+static int mlx4_en_get_rxfh_indir(struct net_device *dev, u32 *ring_index)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_rss_map *rss_map = &priv->rss_map;
+ int rss_rings;
+ size_t n = priv->rx_ring_num;
+ int err = 0;
+
+ rss_rings = priv->prof->rss_rings ?: priv->rx_ring_num;
+
+ while (n--) {
+ ring_index[n] = rss_map->qps[n % rss_rings].qpn -
+ rss_map->base_qpn;
+ }
+
+ return err;
+}
+
+static int mlx4_en_set_rxfh_indir(struct net_device *dev,
+ const u32 *ring_index)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int port_up = 0;
+ int err = 0;
+ int i;
+ int rss_rings = 0;
+
+ /* Calculate RSS table size and make sure flows are spread evenly
+ * between rings
+ */
+ for (i = 0; i < priv->rx_ring_num; i++) {
+ if (i > 0 && !ring_index[i] && !rss_rings)
+ rss_rings = i;
+
+ if (ring_index[i] != (i % (rss_rings ?: priv->rx_ring_num)))
+ return -EINVAL;
+ }
+
+ if (!rss_rings)
+ rss_rings = priv->rx_ring_num;
+
+ /* RSS table size must be an order of 2 */
+ if (!is_power_of_2(rss_rings))
+ return -EINVAL;
+
+ mutex_lock(&mdev->state_lock);
+ if (priv->port_up) {
+ port_up = 1;
+ mlx4_en_stop_port(dev);
+ }
+
+ priv->prof->rss_rings = rss_rings;
+
+ if (port_up) {
+ err = mlx4_en_start_port(dev);
+ if (err)
+ en_err(priv, "Failed starting port\n");
+ }
+
+ mutex_unlock(&mdev->state_lock);
+ return err;
+}
+
+static int mlx4_en_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
+ u32 *rule_locs)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ int err = 0;
+
+ switch (cmd->cmd) {
+ case ETHTOOL_GRXRINGS:
+ cmd->data = priv->rx_ring_num;
+ break;
+ default:
+ err = -EOPNOTSUPP;
+ break;
+ }
+
+ return err;
+}
+
const struct ethtool_ops mlx4_en_ethtool_ops = {
.get_drvinfo = mlx4_en_get_drvinfo,
.get_settings = mlx4_en_get_settings,
@@ -498,6 +621,10 @@ const struct ethtool_ops mlx4_en_ethtool_ops = {
.set_pauseparam = mlx4_en_set_pauseparam,
.get_ringparam = mlx4_en_get_ringparam,
.set_ringparam = mlx4_en_set_ringparam,
+ .get_rxnfc = mlx4_en_get_rxnfc,
+ .get_rxfh_indir_size = mlx4_en_get_rxfh_indir_size,
+ .get_rxfh_indir = mlx4_en_get_rxfh_indir,
+ .set_rxfh_indir = mlx4_en_set_rxfh_indir,
};
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c
index a06096fcc0b8..2097a7d3c5b8 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c
@@ -62,10 +62,6 @@ static const char mlx4_en_version[] =
* Device scope module parameters
*/
-
-/* Enable RSS TCP traffic */
-MLX4_EN_PARM_INT(tcp_rss, 1,
- "Enable RSS for incomming TCP traffic or disabled (0)");
/* Enable RSS UDP traffic */
MLX4_EN_PARM_INT(udp_rss, 1,
"Enable RSS for incomming UDP traffic or disabled (0)");
@@ -104,7 +100,6 @@ static int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
struct mlx4_en_profile *params = &mdev->profile;
int i;
- params->tcp_rss = tcp_rss;
params->udp_rss = udp_rss;
if (params->udp_rss && !(mdev->dev->caps.flags
& MLX4_DEV_CAP_FLAG_UDP_RSS)) {
@@ -120,6 +115,7 @@ static int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
params->prof[i].rx_ring_size = MLX4_EN_DEF_RX_RING_SIZE;
params->prof[i].tx_ring_num = MLX4_EN_NUM_TX_RINGS +
(!!pfcrx) * MLX4_EN_NUM_PPP_RINGS;
+ params->prof[i].rss_rings = 0;
}
return 0;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 72fa807b69ce..467ae5824875 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -702,6 +702,8 @@ int mlx4_en_start_port(struct net_device *dev)
/* Schedule multicast task to populate multicast list */
queue_work(mdev->workqueue, &priv->mcast_task);
+ mlx4_set_stats_bitmap(mdev->dev, &priv->stats_bitmap);
+
priv->port_up = true;
netif_tx_start_all_queues(dev);
return 0;
@@ -807,38 +809,50 @@ static void mlx4_en_restart(struct work_struct *work)
mutex_unlock(&mdev->state_lock);
}
-
-static int mlx4_en_open(struct net_device *dev)
+static void mlx4_en_clear_stats(struct net_device *dev)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
struct mlx4_en_dev *mdev = priv->mdev;
int i;
- int err = 0;
-
- mutex_lock(&mdev->state_lock);
-
- if (!mdev->device_up) {
- en_err(priv, "Cannot open - device down/disabled\n");
- err = -EBUSY;
- goto out;
- }
- /* Reset HW statistics and performance counters */
if (mlx4_en_DUMP_ETH_STATS(mdev, priv->port, 1))
en_dbg(HW, priv, "Failed dumping statistics\n");
memset(&priv->stats, 0, sizeof(priv->stats));
memset(&priv->pstats, 0, sizeof(priv->pstats));
+ memset(&priv->pkstats, 0, sizeof(priv->pkstats));
+ memset(&priv->port_stats, 0, sizeof(priv->port_stats));
for (i = 0; i < priv->tx_ring_num; i++) {
priv->tx_ring[i].bytes = 0;
priv->tx_ring[i].packets = 0;
+ priv->tx_ring[i].tx_csum = 0;
}
for (i = 0; i < priv->rx_ring_num; i++) {
priv->rx_ring[i].bytes = 0;
priv->rx_ring[i].packets = 0;
+ priv->rx_ring[i].csum_ok = 0;
+ priv->rx_ring[i].csum_none = 0;
+ }
+}
+
+static int mlx4_en_open(struct net_device *dev)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int err = 0;
+
+ mutex_lock(&mdev->state_lock);
+
+ if (!mdev->device_up) {
+ en_err(priv, "Cannot open - device down/disabled\n");
+ err = -EBUSY;
+ goto out;
}
+ /* Reset HW statistics and SW counters */
+ mlx4_en_clear_stats(dev);
+
err = mlx4_en_start_port(dev);
if (err)
en_err(priv, "Failed starting port:%d\n", priv->port);
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index e8d6ad2dce0a..971d4b6b8dfe 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -853,6 +853,7 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
struct mlx4_en_rss_map *rss_map = &priv->rss_map;
struct mlx4_qp_context context;
struct mlx4_rss_context *rss_context;
+ int rss_rings;
void *ptr;
u8 rss_mask = (MLX4_RSS_IPV4 | MLX4_RSS_TCP_IPV4 | MLX4_RSS_IPV6 |
MLX4_RSS_TCP_IPV6);
@@ -893,10 +894,15 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
mlx4_en_fill_qp_context(priv, 0, 0, 0, 1, priv->base_qpn,
priv->rx_ring[0].cqn, &context);
+ if (!priv->prof->rss_rings || priv->prof->rss_rings > priv->rx_ring_num)
+ rss_rings = priv->rx_ring_num;
+ else
+ rss_rings = priv->prof->rss_rings;
+
ptr = ((void *) &context) + offsetof(struct mlx4_qp_context, pri_path)
+ MLX4_RSS_OFFSET_IN_QPC_PRI_PATH;
rss_context = ptr;
- rss_context->base_qpn = cpu_to_be32(ilog2(priv->rx_ring_num) << 24 |
+ rss_context->base_qpn = cpu_to_be32(ilog2(rss_rings) << 24 |
(rss_map->base_qpn));
rss_context->default_qpn = cpu_to_be32(rss_map->base_qpn);
if (priv->mdev->profile.udp_rss) {
diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c
index 1e9b55eb7217..55d7bd4e210a 100644
--- a/drivers/net/ethernet/mellanox/mlx4/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/eq.c
@@ -513,25 +513,22 @@ int mlx4_MAP_EQ_wrapper(struct mlx4_dev *dev, int slave,
{
struct mlx4_priv *priv = mlx4_priv(dev);
struct mlx4_slave_event_eq_info *event_eq =
- &priv->mfunc.master.slave_state[slave].event_eq;
+ priv->mfunc.master.slave_state[slave].event_eq;
u32 in_modifier = vhcr->in_modifier;
u32 eqn = in_modifier & 0x1FF;
u64 in_param = vhcr->in_param;
int err = 0;
+ int i;
if (slave == dev->caps.function)
err = mlx4_cmd(dev, in_param, (in_modifier & 0x80000000) | eqn,
0, MLX4_CMD_MAP_EQ, MLX4_CMD_TIME_CLASS_B,
MLX4_CMD_NATIVE);
- if (!err) {
- if (in_modifier >> 31) {
- /* unmap */
- event_eq->event_type &= ~in_param;
- } else {
- event_eq->eqn = eqn;
- event_eq->event_type = in_param;
- }
- }
+ if (!err)
+ for (i = 0; i < MLX4_EVENT_TYPES_NUM; ++i)
+ if (in_param & (1LL << i))
+ event_eq[i].eqn = in_modifier >> 31 ? -1 : eqn;
+
return err;
}
@@ -546,7 +543,7 @@ static int mlx4_MAP_EQ(struct mlx4_dev *dev, u64 event_mask, int unmap,
static int mlx4_SW2HW_EQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
int eq_num)
{
- return mlx4_cmd(dev, mailbox->dma | dev->caps.function, eq_num, 0,
+ return mlx4_cmd(dev, mailbox->dma, eq_num, 0,
MLX4_CMD_SW2HW_EQ, MLX4_CMD_TIME_CLASS_A,
MLX4_CMD_WRAPPED);
}
@@ -554,7 +551,7 @@ static int mlx4_SW2HW_EQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
static int mlx4_HW2SW_EQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
int eq_num)
{
- return mlx4_cmd_box(dev, dev->caps.function, mailbox->dma, eq_num,
+ return mlx4_cmd_box(dev, 0, mailbox->dma, eq_num,
0, MLX4_CMD_HW2SW_EQ, MLX4_CMD_TIME_CLASS_A,
MLX4_CMD_WRAPPED);
}
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c
index a424a19280cc..8a21e10952ea 100644
--- a/drivers/net/ethernet/mellanox/mlx4/fw.c
+++ b/drivers/net/ethernet/mellanox/mlx4/fw.c
@@ -158,7 +158,6 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave,
#define QUERY_FUNC_CAP_FLAGS_OFFSET 0x0
#define QUERY_FUNC_CAP_NUM_PORTS_OFFSET 0x1
-#define QUERY_FUNC_CAP_FUNCTION_OFFSET 0x3
#define QUERY_FUNC_CAP_PF_BHVR_OFFSET 0x4
#define QUERY_FUNC_CAP_QP_QUOTA_OFFSET 0x10
#define QUERY_FUNC_CAP_CQ_QUOTA_OFFSET 0x14
@@ -182,9 +181,6 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave,
field = 1 << 7; /* enable only ethernet interface */
MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS_OFFSET);
- field = slave;
- MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FUNCTION_OFFSET);
-
field = dev->caps.num_ports;
MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_NUM_PORTS_OFFSET);
@@ -249,9 +245,6 @@ int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, struct mlx4_func_cap *func_cap)
goto out;
}
- MLX4_GET(field, outbox, QUERY_FUNC_CAP_FUNCTION_OFFSET);
- func_cap->function = field;
-
MLX4_GET(field, outbox, QUERY_FUNC_CAP_NUM_PORTS_OFFSET);
func_cap->num_ports = field;
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.h b/drivers/net/ethernet/mellanox/mlx4/fw.h
index 119e0cc9fab3..e1a5fa56bcbc 100644
--- a/drivers/net/ethernet/mellanox/mlx4/fw.h
+++ b/drivers/net/ethernet/mellanox/mlx4/fw.h
@@ -119,7 +119,6 @@ struct mlx4_dev_cap {
};
struct mlx4_func_cap {
- u8 function;
u8 num_ports;
u8 flags;
u32 pf_context_behaviour;
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index 6bb62c580e2d..678558b502fc 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -108,7 +108,7 @@ static struct mlx4_profile default_profile = {
.num_cq = 1 << 16,
.num_mcg = 1 << 13,
.num_mpt = 1 << 19,
- .num_mtt = 1 << 20,
+ .num_mtt = 1 << 20, /* It is really num mtt segements */
};
static int log_num_mac = 7;
@@ -471,7 +471,6 @@ static int mlx4_slave_cap(struct mlx4_dev *dev)
return -ENOSYS;
}
- dev->caps.function = func_cap.function;
dev->caps.num_ports = func_cap.num_ports;
dev->caps.num_qps = func_cap.qp_quota;
dev->caps.num_srqs = func_cap.srq_quota;
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
index a80121a2b519..c92269f8c057 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
@@ -388,9 +388,8 @@ struct mlx4_slave_eqe {
};
struct mlx4_slave_event_eq_info {
- u32 eqn;
+ int eqn;
u16 token;
- u64 event_type;
};
struct mlx4_profile {
@@ -449,6 +448,8 @@ struct mlx4_steer_index {
struct list_head duplicates;
};
+#define MLX4_EVENT_TYPES_NUM 64
+
struct mlx4_slave_state {
u8 comm_toggle;
u8 last_cmd;
@@ -461,7 +462,8 @@ struct mlx4_slave_state {
struct mlx4_slave_eqe eq[MLX4_MFUNC_MAX_EQES];
struct list_head mcast_filters[MLX4_MAX_PORTS + 1];
struct mlx4_vlan_fltr *vlan_filter[MLX4_MAX_PORTS + 1];
- struct mlx4_slave_event_eq_info event_eq;
+ /* event type to eq number lookup */
+ struct mlx4_slave_event_eq_info event_eq[MLX4_EVENT_TYPES_NUM];
u16 eq_pi;
u16 eq_ci;
spinlock_t lock;
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index f2a8e65f5f88..35f08840813c 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -325,11 +325,11 @@ struct mlx4_en_port_profile {
u8 rx_ppp;
u8 tx_pause;
u8 tx_ppp;
+ int rss_rings;
};
struct mlx4_en_profile {
int rss_xor;
- int tcp_rss;
int udp_rss;
u8 rss_mask;
u32 active_ports;
@@ -476,6 +476,7 @@ struct mlx4_en_priv {
struct mlx4_en_perf_stats pstats;
struct mlx4_en_pkt_stats pkstats;
struct mlx4_en_port_stats port_stats;
+ u64 stats_bitmap;
char *mc_addrs;
int mc_addrs_cnt;
struct mlx4_en_stat_out_mbox hw_stats;
diff --git a/drivers/net/ethernet/mellanox/mlx4/mr.c b/drivers/net/ethernet/mellanox/mlx4/mr.c
index 01df5567e16e..8deeef98280c 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mr.c
+++ b/drivers/net/ethernet/mellanox/mlx4/mr.c
@@ -291,7 +291,7 @@ static u32 key_to_hw_index(u32 key)
static int mlx4_SW2HW_MPT(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
int mpt_index)
{
- return mlx4_cmd(dev, mailbox->dma | dev->caps.function , mpt_index,
+ return mlx4_cmd(dev, mailbox->dma, mpt_index,
0, MLX4_CMD_SW2HW_MPT, MLX4_CMD_TIME_CLASS_B,
MLX4_CMD_WRAPPED);
}
diff --git a/drivers/net/ethernet/mellanox/mlx4/pd.c b/drivers/net/ethernet/mellanox/mlx4/pd.c
index 5c9a54df17ab..db4746d0dca7 100644
--- a/drivers/net/ethernet/mellanox/mlx4/pd.c
+++ b/drivers/net/ethernet/mellanox/mlx4/pd.c
@@ -52,8 +52,7 @@ int mlx4_pd_alloc(struct mlx4_dev *dev, u32 *pdn)
*pdn = mlx4_bitmap_alloc(&priv->pd_bitmap);
if (*pdn == -1)
return -ENOMEM;
- if (mlx4_is_mfunc(dev))
- *pdn |= (dev->caps.function + 1) << NOT_MASKED_PD_BITS;
+
return 0;
}
EXPORT_SYMBOL_GPL(mlx4_pd_alloc);
diff --git a/drivers/net/ethernet/mellanox/mlx4/port.c b/drivers/net/ethernet/mellanox/mlx4/port.c
index 88b52e547524..f44ae555bf43 100644
--- a/drivers/net/ethernet/mellanox/mlx4/port.c
+++ b/drivers/net/ethernet/mellanox/mlx4/port.c
@@ -44,6 +44,11 @@
#define MLX4_VLAN_VALID (1u << 31)
#define MLX4_VLAN_MASK 0xfff
+#define MLX4_STATS_TRAFFIC_COUNTERS_MASK 0xfULL
+#define MLX4_STATS_TRAFFIC_DROPS_MASK 0xc0ULL
+#define MLX4_STATS_ERROR_COUNTERS_MASK 0x1ffc30ULL
+#define MLX4_STATS_PORT_COUNTERS_MASK 0x1fe00000ULL
+
void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table)
{
int i;
@@ -898,6 +903,24 @@ int mlx4_DUMP_ETH_STATS_wrapper(struct mlx4_dev *dev, int slave,
struct mlx4_cmd_mailbox *outbox,
struct mlx4_cmd_info *cmd)
{
+ if (slave != dev->caps.function)
+ return 0;
return mlx4_common_dump_eth_stats(dev, slave,
vhcr->in_modifier, outbox);
}
+
+void mlx4_set_stats_bitmap(struct mlx4_dev *dev, u64 *stats_bitmap)
+{
+ if (!mlx4_is_mfunc(dev)) {
+ *stats_bitmap = 0;
+ return;
+ }
+
+ *stats_bitmap = (MLX4_STATS_TRAFFIC_COUNTERS_MASK |
+ MLX4_STATS_TRAFFIC_DROPS_MASK |
+ MLX4_STATS_PORT_COUNTERS_MASK);
+
+ if (mlx4_is_master(dev))
+ *stats_bitmap |= MLX4_STATS_ERROR_COUNTERS_MASK;
+}
+EXPORT_SYMBOL(mlx4_set_stats_bitmap);
diff --git a/drivers/net/ethernet/mellanox/mlx4/profile.c b/drivers/net/ethernet/mellanox/mlx4/profile.c
index 66f91ca7a7c6..1129677daa62 100644
--- a/drivers/net/ethernet/mellanox/mlx4/profile.c
+++ b/drivers/net/ethernet/mellanox/mlx4/profile.c
@@ -110,7 +110,7 @@ u64 mlx4_make_profile(struct mlx4_dev *dev,
profile[MLX4_RES_EQ].num = min_t(unsigned, dev_cap->max_eqs, MAX_MSIX);
profile[MLX4_RES_DMPT].num = request->num_mpt;
profile[MLX4_RES_CMPT].num = MLX4_NUM_CMPTS;
- profile[MLX4_RES_MTT].num = request->num_mtt;
+ profile[MLX4_RES_MTT].num = request->num_mtt * (1 << log_mtts_per_seg);
profile[MLX4_RES_MCG].num = request->num_mcg;
for (i = 0; i < MLX4_RES_NUM; ++i) {
diff --git a/drivers/net/ethernet/mellanox/mlx4/qp.c b/drivers/net/ethernet/mellanox/mlx4/qp.c
index 6b03ac8b9002..738f950a1ce5 100644
--- a/drivers/net/ethernet/mellanox/mlx4/qp.c
+++ b/drivers/net/ethernet/mellanox/mlx4/qp.c
@@ -162,7 +162,7 @@ static int __mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
((struct mlx4_qp_context *) (mailbox->buf + 8))->local_qpn =
cpu_to_be32(qp->qpn);
- ret = mlx4_cmd(dev, mailbox->dma | dev->caps.function,
+ ret = mlx4_cmd(dev, mailbox->dma,
qp->qpn | (!!sqd_event << 31),
new_state == MLX4_QP_STATE_RST ? 2 : 0,
op[cur_state][new_state], MLX4_CMD_TIME_CLASS_C, native);
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
index ed20751a057d..dcd819bfb2f0 100644
--- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
+++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
@@ -1561,11 +1561,6 @@ static int mr_get_mtt_size(struct mlx4_mpt_entry *mpt)
return be32_to_cpu(mpt->mtt_sz);
}
-static int mr_get_pdn(struct mlx4_mpt_entry *mpt)
-{
- return be32_to_cpu(mpt->pd_flags) & 0xffffff;
-}
-
static int qp_get_mtt_addr(struct mlx4_qp_context *qpc)
{
return be32_to_cpu(qpc->mtt_base_addr_l) & 0xfffffff8;
@@ -1602,16 +1597,6 @@ static int qp_get_mtt_size(struct mlx4_qp_context *qpc)
return total_pages;
}
-static int qp_get_pdn(struct mlx4_qp_context *qpc)
-{
- return be32_to_cpu(qpc->pd) & 0xffffff;
-}
-
-static int pdn2slave(int pdn)
-{
- return (pdn >> NOT_MASKED_PD_BITS) - 1;
-}
-
static int check_mtt_range(struct mlx4_dev *dev, int slave, int start,
int size, struct res_mtt *mtt)
{
@@ -1656,11 +1641,6 @@ int mlx4_SW2HW_MPT_wrapper(struct mlx4_dev *dev, int slave,
mpt->mtt = mtt;
}
- if (pdn2slave(mr_get_pdn(inbox->buf)) != slave) {
- err = -EPERM;
- goto ex_put;
- }
-
err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
if (err)
goto ex_put;
@@ -1792,11 +1772,6 @@ int mlx4_RST2INIT_QP_wrapper(struct mlx4_dev *dev, int slave,
if (err)
goto ex_put_mtt;
- if (pdn2slave(qp_get_pdn(qpc)) != slave) {
- err = -EPERM;
- goto ex_put_mtt;
- }
-
err = get_res(dev, slave, rcqn, RES_CQ, &rcq);
if (err)
goto ex_put_mtt;
@@ -2048,10 +2023,10 @@ int mlx4_GEN_EQE(struct mlx4_dev *dev, int slave, struct mlx4_eqe *eqe)
if (!priv->mfunc.master.slave_state)
return -EINVAL;
- event_eq = &priv->mfunc.master.slave_state[slave].event_eq;
+ event_eq = &priv->mfunc.master.slave_state[slave].event_eq[eqe->type];
/* Create the event only if the slave is registered */
- if ((event_eq->event_type & (1 << eqe->type)) == 0)
+ if (event_eq->eqn < 0)
return 0;
mutex_lock(&priv->mfunc.master.gen_eqe_mutex[slave]);
@@ -2289,11 +2264,6 @@ ex_put:
return err;
}
-static int srq_get_pdn(struct mlx4_srq_context *srqc)
-{
- return be32_to_cpu(srqc->pd) & 0xffffff;
-}
-
static int srq_get_mtt_size(struct mlx4_srq_context *srqc)
{
int log_srq_size = (be32_to_cpu(srqc->state_logsize_srqn) >> 24) & 0xf;
@@ -2333,11 +2303,6 @@ int mlx4_SW2HW_SRQ_wrapper(struct mlx4_dev *dev, int slave,
if (err)
goto ex_put_mtt;
- if (pdn2slave(srq_get_pdn(srqc)) != slave) {
- err = -EPERM;
- goto ex_put_mtt;
- }
-
err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
if (err)
goto ex_put_mtt;
diff --git a/drivers/net/ethernet/mellanox/mlx4/srq.c b/drivers/net/ethernet/mellanox/mlx4/srq.c
index 2823fffc6383..feda6c00829f 100644
--- a/drivers/net/ethernet/mellanox/mlx4/srq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/srq.c
@@ -67,7 +67,7 @@ void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type)
static int mlx4_SW2HW_SRQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
int srq_num)
{
- return mlx4_cmd(dev, mailbox->dma | dev->caps.function, srq_num, 0,
+ return mlx4_cmd(dev, mailbox->dma, srq_num, 0,
MLX4_CMD_SW2HW_SRQ, MLX4_CMD_TIME_CLASS_A,
MLX4_CMD_WRAPPED);
}
diff --git a/drivers/net/ethernet/micrel/ks8842.c b/drivers/net/ethernet/micrel/ks8842.c
index 75ec87a822b8..0a85690a1321 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/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
index 964e9c0948bc..3ead111111e1 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
@@ -1745,6 +1745,12 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter)
struct pch_gbe_rx_ring *rx_ring = adapter->rx_ring;
int err;
+ /* Ensure we have a valid MAC */
+ if (!is_valid_ether_addr(adapter->hw.mac.addr)) {
+ pr_err("Error: Invalid MAC address\n");
+ return -EINVAL;
+ }
+
/* hardware has been reset, we need to reload some things */
pch_gbe_set_multi(netdev);
@@ -2468,9 +2474,14 @@ static int pch_gbe_probe(struct pci_dev *pdev,
memcpy(netdev->dev_addr, adapter->hw.mac.addr, netdev->addr_len);
if (!is_valid_ether_addr(netdev->dev_addr)) {
- dev_err(&pdev->dev, "Invalid MAC Address\n");
- ret = -EIO;
- goto err_free_adapter;
+ /*
+ * If the MAC is invalid (or just missing), display a warning
+ * but do not abort setting up the device. pch_gbe_up will
+ * prevent the interface from being brought up until a valid MAC
+ * is set.
+ */
+ dev_err(&pdev->dev, "Invalid MAC address, "
+ "interface disabled.\n");
}
setup_timer(&adapter->watchdog_timer, pch_gbe_watchdog,
(unsigned long)adapter);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
index da4a1042523a..73195329aa46 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
@@ -154,7 +154,7 @@ int stmmac_mdio_register(struct net_device *ndev)
else
irqlist = priv->mii_irq;
- new_bus->name = "STMMAC MII Bus";
+ new_bus->name = "stmmac";
new_bus->read = &stmmac_mdio_read;
new_bus->write = &stmmac_mdio_write;
new_bus->reset = &stmmac_mdio_reset;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
index 54a819a36487..c796de9eed72 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
@@ -170,9 +170,9 @@ static int stmmac_pci_resume(struct pci_dev *pdev)
#define STMMAC_DEVICE_ID 0x1108
static DEFINE_PCI_DEVICE_TABLE(stmmac_id_table) = {
- {
- PCI_DEVICE(STMMAC_VENDOR_ID, STMMAC_DEVICE_ID)}, {
- }
+ {PCI_DEVICE(STMMAC_VENDOR_ID, STMMAC_DEVICE_ID)},
+ {PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_MAC)},
+ {}
};
MODULE_DEVICE_TABLE(pci, stmmac_id_table);
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 462d05f05e84..1a1ca6cfc74a 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -68,11 +68,11 @@ static void do_set_multicast(struct work_struct *w)
nvdev = hv_get_drvdata(ndevctx->device_ctx);
if (nvdev == NULL)
- return;
+ goto out;
rdev = nvdev->extension;
if (rdev == NULL)
- return;
+ goto out;
if (net->flags & IFF_PROMISC)
rndis_filter_set_packet_filter(rdev,
@@ -83,6 +83,7 @@ static void do_set_multicast(struct work_struct *w)
NDIS_PACKET_TYPE_ALL_MULTICAST |
NDIS_PACKET_TYPE_DIRECTED);
+out:
kfree(w);
}
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
index d423d18b4ad6..e535137eb2d0 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 c072c09a8d91..000000000000
--- 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 a3d696a9456a..fc503aa5288e 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/macvlan.c b/drivers/net/macvlan.c
index f2f820c4b40a..9ea99217f116 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -173,6 +173,7 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb)
skb = ip_check_defrag(skb, IP_DEFRAG_MACVLAN);
if (!skb)
return RX_HANDLER_CONSUMED;
+ eth = eth_hdr(skb);
src = macvlan_hash_lookup(port, eth->h_source);
if (!src)
/* frame comes from an external address */
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 88cc5db9affd..8985cc62cf41 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -38,12 +38,11 @@
/**
* mdiobus_alloc_size - allocate a mii_bus structure
+ * @size: extra amount of memory to allocate for private storage.
+ * If non-zero, then bus->priv is points to that memory.
*
* 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_size(size_t size)
{
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index ed2a862b835d..6b678f38e5ce 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -92,9 +92,9 @@ struct team_option *__team_find_option(struct team *team, const char *opt_name)
return NULL;
}
-int team_options_register(struct team *team,
- const struct team_option *option,
- size_t option_count)
+int __team_options_register(struct team *team,
+ const struct team_option *option,
+ size_t option_count)
{
int i;
struct team_option **dst_opts;
@@ -116,8 +116,11 @@ int team_options_register(struct team *team,
}
}
- for (i = 0; i < option_count; i++)
+ for (i = 0; i < option_count; i++) {
+ dst_opts[i]->changed = true;
+ dst_opts[i]->removed = false;
list_add_tail(&dst_opts[i]->list, &team->option_list);
+ }
kfree(dst_opts);
return 0;
@@ -130,10 +133,22 @@ rollback:
return err;
}
-EXPORT_SYMBOL(team_options_register);
+static void __team_options_mark_removed(struct team *team,
+ const struct team_option *option,
+ size_t option_count)
+{
+ int i;
+
+ for (i = 0; i < option_count; i++, option++) {
+ struct team_option *del_opt;
-static void __team_options_change_check(struct team *team,
- struct team_option *changed_option);
+ del_opt = __team_find_option(team, option->name);
+ if (del_opt) {
+ del_opt->changed = true;
+ del_opt->removed = true;
+ }
+ }
+}
static void __team_options_unregister(struct team *team,
const struct team_option *option,
@@ -152,12 +167,29 @@ static void __team_options_unregister(struct team *team,
}
}
+static void __team_options_change_check(struct team *team);
+
+int team_options_register(struct team *team,
+ const struct team_option *option,
+ size_t option_count)
+{
+ int err;
+
+ err = __team_options_register(team, option, option_count);
+ if (err)
+ return err;
+ __team_options_change_check(team);
+ return 0;
+}
+EXPORT_SYMBOL(team_options_register);
+
void team_options_unregister(struct team *team,
const struct team_option *option,
size_t option_count)
{
+ __team_options_mark_removed(team, option, option_count);
+ __team_options_change_check(team);
__team_options_unregister(team, option, option_count);
- __team_options_change_check(team, NULL);
}
EXPORT_SYMBOL(team_options_unregister);
@@ -176,7 +208,8 @@ static int team_option_set(struct team *team, struct team_option *option,
if (err)
return err;
- __team_options_change_check(team, option);
+ option->changed = true;
+ __team_options_change_check(team);
return err;
}
@@ -653,6 +686,7 @@ static int team_port_del(struct team *team, struct net_device *port_dev)
return -ENOENT;
}
+ port->removed = true;
__team_port_change_check(port, false);
team_port_list_del_port(team, port);
team_adjust_ops(team);
@@ -1200,10 +1234,9 @@ err_fill:
return err;
}
-static int team_nl_fill_options_get_changed(struct sk_buff *skb,
- u32 pid, u32 seq, int flags,
- struct team *team,
- struct team_option *changed_option)
+static int team_nl_fill_options_get(struct sk_buff *skb,
+ u32 pid, u32 seq, int flags,
+ struct team *team, bool fillall)
{
struct nlattr *option_list;
void *hdr;
@@ -1223,12 +1256,19 @@ static int team_nl_fill_options_get_changed(struct sk_buff *skb,
struct nlattr *option_item;
long arg;
+ /* Include only changed options if fill all mode is not on */
+ if (!fillall && !option->changed)
+ continue;
option_item = nla_nest_start(skb, TEAM_ATTR_ITEM_OPTION);
if (!option_item)
goto nla_put_failure;
NLA_PUT_STRING(skb, TEAM_ATTR_OPTION_NAME, option->name);
- if (option == changed_option)
+ if (option->changed) {
NLA_PUT_FLAG(skb, TEAM_ATTR_OPTION_CHANGED);
+ option->changed = false;
+ }
+ if (option->removed)
+ NLA_PUT_FLAG(skb, TEAM_ATTR_OPTION_REMOVED);
switch (option->type) {
case TEAM_OPTION_TYPE_U32:
NLA_PUT_U8(skb, TEAM_ATTR_OPTION_TYPE, NLA_U32);
@@ -1255,13 +1295,13 @@ nla_put_failure:
return -EMSGSIZE;
}
-static int team_nl_fill_options_get(struct sk_buff *skb,
- struct genl_info *info, int flags,
- struct team *team)
+static int team_nl_fill_options_get_all(struct sk_buff *skb,
+ struct genl_info *info, int flags,
+ struct team *team)
{
- return team_nl_fill_options_get_changed(skb, info->snd_pid,
- info->snd_seq, NLM_F_ACK,
- team, NULL);
+ return team_nl_fill_options_get(skb, info->snd_pid,
+ info->snd_seq, NLM_F_ACK,
+ team, true);
}
static int team_nl_cmd_options_get(struct sk_buff *skb, struct genl_info *info)
@@ -1273,7 +1313,7 @@ static int team_nl_cmd_options_get(struct sk_buff *skb, struct genl_info *info)
if (!team)
return -EINVAL;
- err = team_nl_send_generic(info, team, team_nl_fill_options_get);
+ err = team_nl_send_generic(info, team, team_nl_fill_options_get_all);
team_nl_team_put(team);
@@ -1365,10 +1405,10 @@ team_put:
return err;
}
-static int team_nl_fill_port_list_get_changed(struct sk_buff *skb,
- u32 pid, u32 seq, int flags,
- struct team *team,
- struct team_port *changed_port)
+static int team_nl_fill_port_list_get(struct sk_buff *skb,
+ u32 pid, u32 seq, int flags,
+ struct team *team,
+ bool fillall)
{
struct nlattr *port_list;
void *hdr;
@@ -1387,12 +1427,19 @@ static int team_nl_fill_port_list_get_changed(struct sk_buff *skb,
list_for_each_entry(port, &team->port_list, list) {
struct nlattr *port_item;
+ /* Include only changed ports if fill all mode is not on */
+ if (!fillall && !port->changed)
+ continue;
port_item = nla_nest_start(skb, TEAM_ATTR_ITEM_PORT);
if (!port_item)
goto nla_put_failure;
NLA_PUT_U32(skb, TEAM_ATTR_PORT_IFINDEX, port->dev->ifindex);
- if (port == changed_port)
+ if (port->changed) {
NLA_PUT_FLAG(skb, TEAM_ATTR_PORT_CHANGED);
+ port->changed = false;
+ }
+ if (port->removed)
+ NLA_PUT_FLAG(skb, TEAM_ATTR_PORT_REMOVED);
if (port->linkup)
NLA_PUT_FLAG(skb, TEAM_ATTR_PORT_LINKUP);
NLA_PUT_U32(skb, TEAM_ATTR_PORT_SPEED, port->speed);
@@ -1408,13 +1455,13 @@ nla_put_failure:
return -EMSGSIZE;
}
-static int team_nl_fill_port_list_get(struct sk_buff *skb,
- struct genl_info *info, int flags,
- struct team *team)
+static int team_nl_fill_port_list_get_all(struct sk_buff *skb,
+ struct genl_info *info, int flags,
+ struct team *team)
{
- return team_nl_fill_port_list_get_changed(skb, info->snd_pid,
- info->snd_seq, NLM_F_ACK,
- team, NULL);
+ return team_nl_fill_port_list_get(skb, info->snd_pid,
+ info->snd_seq, NLM_F_ACK,
+ team, true);
}
static int team_nl_cmd_port_list_get(struct sk_buff *skb,
@@ -1427,7 +1474,7 @@ static int team_nl_cmd_port_list_get(struct sk_buff *skb,
if (!team)
return -EINVAL;
- err = team_nl_send_generic(info, team, team_nl_fill_port_list_get);
+ err = team_nl_send_generic(info, team, team_nl_fill_port_list_get_all);
team_nl_team_put(team);
@@ -1464,8 +1511,7 @@ static struct genl_multicast_group team_change_event_mcgrp = {
.name = TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME,
};
-static int team_nl_send_event_options_get(struct team *team,
- struct team_option *changed_option)
+static int team_nl_send_event_options_get(struct team *team)
{
struct sk_buff *skb;
int err;
@@ -1475,8 +1521,7 @@ static int team_nl_send_event_options_get(struct team *team,
if (!skb)
return -ENOMEM;
- err = team_nl_fill_options_get_changed(skb, 0, 0, 0, team,
- changed_option);
+ err = team_nl_fill_options_get(skb, 0, 0, 0, team, false);
if (err < 0)
goto err_fill;
@@ -1489,18 +1534,17 @@ err_fill:
return err;
}
-static int team_nl_send_event_port_list_get(struct team_port *port)
+static int team_nl_send_event_port_list_get(struct team *team)
{
struct sk_buff *skb;
int err;
- struct net *net = dev_net(port->team->dev);
+ struct net *net = dev_net(team->dev);
skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
if (!skb)
return -ENOMEM;
- err = team_nl_fill_port_list_get_changed(skb, 0, 0, 0,
- port->team, port);
+ err = team_nl_fill_port_list_get(skb, 0, 0, 0, team, false);
if (err < 0)
goto err_fill;
@@ -1544,12 +1588,11 @@ static void team_nl_fini(void)
* Change checkers
******************/
-static void __team_options_change_check(struct team *team,
- struct team_option *changed_option)
+static void __team_options_change_check(struct team *team)
{
int err;
- err = team_nl_send_event_options_get(team, changed_option);
+ err = team_nl_send_event_options_get(team);
if (err)
netdev_warn(team->dev, "Failed to send options change via netlink\n");
}
@@ -1559,9 +1602,10 @@ static void __team_port_change_check(struct team_port *port, bool linkup)
{
int err;
- if (port->linkup == linkup)
+ if (!port->removed && port->linkup == linkup)
return;
+ port->changed = true;
port->linkup = linkup;
if (linkup) {
struct ethtool_cmd ecmd;
@@ -1577,7 +1621,7 @@ static void __team_port_change_check(struct team_port *port, bool linkup)
port->duplex = 0;
send_event:
- err = team_nl_send_event_port_list_get(port);
+ err = team_nl_send_event_port_list_get(port->team);
if (err)
netdev_warn(port->team->dev, "Failed to send port change of device %s via netlink\n",
port->dev->name);
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index ee7759575050..87db1ee1c298 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1037,13 +1037,16 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
/*
* Workaround for early ACK timeouts, add an offset to match the
- * initval's 64us ack timeout value.
+ * initval's 64us ack timeout value. Use 48us for the CTS timeout.
* This was initially only meant to work around an issue with delayed
* BA frames in some implementations, but it has been found to fix ACK
* timeout issues in other cases as well.
*/
- if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ)
+ if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ) {
acktimeout += 64 - sifstime - ah->slottime;
+ ctstimeout += 48 - sifstime - ah->slottime;
+ }
+
ath9k_hw_set_sifs_time(ah, sifstime);
ath9k_hw_setslottime(ah, slottime);
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index abf943557dee..53a005d288aa 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -822,6 +822,11 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,
ARRAY_SIZE(ath9k_tpt_blink));
#endif
+ INIT_WORK(&sc->hw_reset_work, ath_reset_work);
+ INIT_WORK(&sc->hw_check_work, ath_hw_check);
+ INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
+ INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);
+
/* Register with mac80211 */
error = ieee80211_register_hw(hw);
if (error)
@@ -840,10 +845,6 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,
goto error_world;
}
- INIT_WORK(&sc->hw_reset_work, ath_reset_work);
- INIT_WORK(&sc->hw_check_work, ath_hw_check);
- INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
- INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);
sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
ath_init_leds(sc);
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index 635b592ad961..a427a16bb739 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -1346,7 +1346,7 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
fc = hdr->frame_control;
for (i = 0; i < sc->hw->max_rates; i++) {
struct ieee80211_tx_rate *rate = &tx_info->status.rates[i];
- if (!rate->count)
+ if (rate->idx < 0 || !rate->count)
break;
final_ts_idx = i;
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 0e666fbe0842..7e1a91af1497 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -822,6 +822,14 @@ static bool ath9k_rx_accept(struct ath_common *common,
(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC |
ATH9K_RXERR_KEYMISS));
+ /*
+ * Key miss events are only relevant for pairwise keys where the
+ * descriptor does contain a valid key index. This has been observed
+ * mostly with CCMP encryption.
+ */
+ if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID)
+ rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS;
+
if (!rx_stats->rs_datalen)
return false;
/*
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index a8c6880af34b..64f8db685dc5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -91,6 +91,7 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv,
tx_cmd->tid_tspec = qc[0] & 0xf;
tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
} else {
+ tx_cmd->tid_tspec = IWL_TID_NON_QOS;
if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
else
@@ -620,7 +621,7 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif,
sta_priv->lq_sta.lq.agg_params.agg_frame_cnt_limit =
sta_priv->max_agg_bufsize;
- IWL_INFO(priv, "Tx aggregation enabled on ra = %pM tid = %d\n",
+ IWL_DEBUG_HT(priv, "Tx aggregation enabled on ra = %pM tid = %d\n",
sta->addr, tid);
return iwl_send_lq_cmd(priv, ctx,
@@ -808,6 +809,8 @@ static void iwl_rx_reply_tx_agg(struct iwl_priv *priv,
u32 status = le16_to_cpu(tx_resp->status.status);
int i;
+ WARN_ON(tid == IWL_TID_NON_QOS);
+
if (agg->wait_for_ba)
IWL_DEBUG_TX_REPLY(priv,
"got tx response w/o block-ack\n");
@@ -1035,10 +1038,13 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
}
__skb_queue_head_init(&skbs);
- priv->tid_data[sta_id][tid].next_reclaimed = next_reclaimed;
- IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d",
- next_reclaimed);
+ if (tid != IWL_TID_NON_QOS) {
+ priv->tid_data[sta_id][tid].next_reclaimed =
+ next_reclaimed;
+ IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d",
+ next_reclaimed);
+ }
/*we can free until ssn % q.n_bd not inclusive */
WARN_ON(iwl_trans_reclaim(trans(priv), sta_id, tid, txq_id,
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index b4779c25a4b3..c20618d92268 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -815,6 +815,7 @@ struct iwl_qosparam_cmd {
#define IWL_INVALID_STATION 255
#define IWL_MAX_TID_COUNT 8
+#define IWL_TID_NON_QOS IWL_MAX_TID_COUNT
#define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2)
#define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8)
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
index 836caf9c68b3..f5cb5d3cd926 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
@@ -1554,6 +1554,7 @@ static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid,
txq->time_stamp = jiffies;
if (unlikely(txq_id >= IWLAGN_FIRST_AMPDU_QUEUE &&
+ tid != IWL_TID_NON_QOS &&
txq_id != trans_pcie->agg_txq[sta_id][tid])) {
/*
* FIXME: this is a uCode bug which need to be addressed,
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index 478d2f12c024..8d8ee639fe56 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -867,7 +867,12 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
ret = mwifiex_set_rf_channel(priv, channel,
priv->adapter->channel_type);
- ret = mwifiex_set_encode(priv, NULL, 0, 0, 1); /* Disable keys */
+ /* As this is new association, clear locally stored
+ * keys and security related flags */
+ priv->sec_info.wpa_enabled = false;
+ priv->sec_info.wpa2_enabled = false;
+ priv->wep_key_curr_index = 0;
+ ret = mwifiex_set_encode(priv, NULL, 0, 0, 1);
if (mode == NL80211_IFTYPE_ADHOC) {
/* "privacy" is set only for ad-hoc mode */
@@ -912,6 +917,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
dev_dbg(priv->adapter->dev,
"info: setting wep encryption"
" with key len %d\n", sme->key_len);
+ priv->wep_key_curr_index = sme->key_idx;
ret = mwifiex_set_encode(priv, sme->key, sme->key_len,
sme->key_idx, 0);
}
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index 83cc10fca4bd..ca59cc0d013e 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -383,7 +383,8 @@ mwifiex_free_adapter(struct mwifiex_adapter *adapter)
adapter->if_ops.cleanup_if(adapter);
- dev_kfree_skb_any(adapter->sleep_cfm);
+ if (adapter->sleep_cfm)
+ dev_kfree_skb_any(adapter->sleep_cfm);
}
/*
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index 80e44566bf6e..790a3796483c 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -811,7 +811,9 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
continue;
rtnl_lock();
- mwifiex_del_virtual_intf(priv->wdev->wiphy, priv->netdev);
+ if (priv->wdev && priv->netdev)
+ mwifiex_del_virtual_intf(priv->wdev->wiphy,
+ priv->netdev);
rtnl_unlock();
}
@@ -819,9 +821,11 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
if (!priv)
goto exit_remove;
- wiphy_unregister(priv->wdev->wiphy);
- wiphy_free(priv->wdev->wiphy);
- kfree(priv->wdev);
+ if (priv->wdev) {
+ wiphy_unregister(priv->wdev->wiphy);
+ wiphy_free(priv->wdev->wiphy);
+ kfree(priv->wdev);
+ }
mwifiex_terminate_workqueue(adapter);
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index 470ca75ec250..b0fbf5d4fea0 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -54,7 +54,7 @@ int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist,
int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter)
{
bool cancel_flag = false;
- int status = adapter->cmd_wait_q.status;
+ int status;
struct cmd_ctrl_node *cmd_queued;
if (!adapter->cmd_queued)
@@ -79,6 +79,8 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter)
mwifiex_cancel_pending_ioctl(adapter);
dev_dbg(adapter->dev, "cmd cancel\n");
}
+
+ status = adapter->cmd_wait_q.status;
adapter->cmd_wait_q.status = 0;
return status;
@@ -240,6 +242,8 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
if (!netif_queue_stopped(priv->netdev))
mwifiex_stop_net_dev_queue(priv->netdev, adapter);
+ if (netif_carrier_ok(priv->netdev))
+ netif_carrier_off(priv->netdev);
/* Clear any past association response stored for
* application retrieval */
@@ -271,6 +275,8 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
if (!netif_queue_stopped(priv->netdev))
mwifiex_stop_net_dev_queue(priv->netdev, adapter);
+ if (netif_carrier_ok(priv->netdev))
+ netif_carrier_off(priv->netdev);
if (!ret) {
dev_dbg(adapter->dev, "info: network found in scan"
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 52728be65271..772d4aec303a 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -513,9 +513,9 @@ EXPORT_SYMBOL_GPL(rt2800_write_tx_data);
static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, u32 rxwi_w2)
{
- int rssi0 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI0);
- int rssi1 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI1);
- int rssi2 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI2);
+ s8 rssi0 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI0);
+ s8 rssi1 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI1);
+ s8 rssi2 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI2);
u16 eeprom;
u8 offset0;
u8 offset1;
@@ -551,7 +551,7 @@ static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, u32 rxwi_w2)
* which gives less energy...
*/
rssi0 = max(rssi0, rssi1);
- return max(rssi0, rssi2);
+ return (int)max(rssi0, rssi2);
}
void rt2800_process_rxwi(struct queue_entry *entry,
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 0a70149df3fc..98a574a4a465 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -866,6 +866,14 @@ static int fill_ctrlset(struct zd_mac *mac,
ZD_ASSERT(frag_len <= 0xffff);
+ /*
+ * Firmware computes the duration itself (for all frames except PSPoll)
+ * and needs the field set to 0 at input, otherwise firmware messes up
+ * duration_id and sets bits 14 and 15 on.
+ */
+ if (!ieee80211_is_pspoll(hdr->frame_control))
+ hdr->duration_id = 0;
+
txrate = ieee80211_get_tx_rate(mac->hw, info);
cs->modulation = txrate->hw_value;
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index fa679057630f..698b905058dd 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -68,7 +68,7 @@ struct netfront_cb {
#define NET_TX_RING_SIZE __CONST_RING_SIZE(xen_netif_tx, PAGE_SIZE)
#define NET_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, PAGE_SIZE)
-#define TX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256)
+#define TX_MAX_TARGET min_t(int, NET_TX_RING_SIZE, 256)
struct netfront_stats {
u64 rx_packets;
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 72c33fbe451d..66d96f14c274 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/irq.c b/drivers/of/irq.c
index 0f0cfa3bca30..9cf00602f566 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/parport/parport_ip32.c b/drivers/parport/parport_ip32.c
index 0dc34f12f92e..d4716273651e 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/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c
index 095f29e13734..2a47e82821da 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 efa9f2de51c1..aa41631e9e02 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 e525263210ee..c35e8ad6db01 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 41f6a8d79c81..6bf8d2ab164f 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 f1ce99cceac6..187a199da93c 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 d934dd4fa873..5506e0e8fbc0 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 6d2eea93298f..202f4a969eb5 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 9a33fdde2d16..4b7cce1de6ec 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 b8c99d35ac97..365c6b96c642 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 5175d9b26f0b..b20ceaaa31f4 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 419919a87b0f..df5677440a08 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 758adb5f47fd..127d6e600185 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 e0c90e643b5f..ca64932e658b 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 dd7e0c51a33e..7414fd9ad1d2 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/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 106be0d08f81..a3cd8cad532a 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 97fff785e97e..af295bb21d62 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -2802,7 +2802,7 @@ pci_intx(struct pci_dev *pdev, int enable)
/**
* pci_intx_mask_supported - probe for INTx masking support
- * @pdev: the PCI device to operate on
+ * @dev: the PCI device to operate on
*
* Check if the device dev support INTx masking via the config space
* command word.
@@ -2884,7 +2884,7 @@ done:
/**
* pci_check_and_mask_intx - mask INTx on pending interrupt
- * @pdev: the PCI device to operate on
+ * @dev: 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
@@ -2898,7 +2898,7 @@ 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
+ * @dev: 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
diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c
index 95489cd9a555..52229863e9fe 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 9674e9f30d49..0ca053538146 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/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 6e318ce41136..f9e3fb3a285b 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 29935ea921df..ec543a4ff2e4 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 95dd7c62741f..000000000000
--- 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 5c36bda2963b..000000000000
--- 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 b2396647a165..000000000000
--- 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 3e49df6d5e3b..5b7c22784aff 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 9dc565c615bd..849c0c11d2af 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/compal-laptop.c b/drivers/platform/x86/compal-laptop.c
index 8877b836d27c..d96734478324 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 7f88c7923fc6..6ee0b5c90933 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 f204643c5052..bb5132128b33 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 09e26bfd4643..fd73ea89b857 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 62533c105da4..ea0c6075b720 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 a134c26870b0..42a4dcc25f92 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/power/ds2760_battery.c b/drivers/power/ds2760_battery.c
index 545874b1df9e..076e211a40b7 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");
diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c
index e91b8ddc2793..c9b92531ae60 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/regulator/core.c b/drivers/regulator/core.c
index ca86f39a0fdc..e9a83f84adaf 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -2731,6 +2731,8 @@ static void rdev_init_debugfs(struct regulator_dev *rdev)
* @dev: struct device for the regulator
* @init_data: platform provided init data, passed through by driver
* @driver_data: private regulator data
+ * @of_node: OpenFirmware node to parse for device tree bindings (may be
+ * NULL).
*
* Called by regulator drivers to register a regulator.
* Returns 0 on success.
diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c
index a0a9810adf0b..4bcf9ca2818a 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
diff --git a/drivers/rtc/rtc-max8925.c b/drivers/rtc/rtc-max8925.c
index 4a5529346b47..2d71943bc436 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,10 +292,34 @@ 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),
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index e5cb9248a442..f3b8bb84faf2 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 11312f401c70..2211277a1079 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 2985eb439485..204ca728e7fd 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/scsi/Kconfig b/drivers/scsi/Kconfig
index 06ea3bcfdd2a..16570aa84aac 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -830,16 +830,11 @@ config SCSI_ISCI
tristate "Intel(R) C600 Series Chipset SAS Controller"
depends on PCI && SCSI
depends on X86
- # (temporary): known alpha quality driver
- depends on EXPERIMENTAL
select SCSI_SAS_LIBSAS
- select SCSI_SAS_HOST_SMP
---help---
This driver supports the 6Gb/s SAS capabilities of the storage
control unit found in the Intel(R) C600 series chipset.
- The experimental tag will be removed after the driver exits alpha
-
config SCSI_GENERIC_NCR5380
tristate "Generic NCR5380/53c400 SCSI PIO support"
depends on ISA && SCSI
diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
index 195823a51aab..ed119cedaae0 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/bfa/bfa_defs_svc.h b/drivers/scsi/bfa/bfa_defs_svc.h
index 78963be2c4fb..cb07c628b2f1 100644
--- a/drivers/scsi/bfa/bfa_defs_svc.h
+++ b/drivers/scsi/bfa/bfa_defs_svc.h
@@ -673,12 +673,7 @@ struct bfa_itnim_iostats_s {
u32 tm_iocdowns; /* TM cleaned-up due to IOC down */
u32 tm_cleanups; /* TM cleanup requests */
u32 tm_cleanup_comps; /* TM cleanup completions */
- u32 lm_lun_across_sg; /* LM lun is across sg data buf */
- u32 lm_lun_not_sup; /* LM lun not supported */
- u32 lm_rpl_data_changed; /* LM report-lun data changed */
- u32 lm_wire_residue_changed; /* LM report-lun rsp residue changed */
- u32 lm_small_buf_addresidue; /* LM buf smaller than reported cnt */
- u32 lm_lun_not_rdy; /* LM lun not ready */
+ u32 rsvd[6];
};
/* Modify char* port_stt[] in bfal_port.c if a new state was added */
diff --git a/drivers/scsi/bfa/bfa_fc.h b/drivers/scsi/bfa/bfa_fc.h
index 50b6a1c86195..8d0b88f67a38 100644
--- a/drivers/scsi/bfa/bfa_fc.h
+++ b/drivers/scsi/bfa/bfa_fc.h
@@ -56,161 +56,6 @@ struct scsi_cdb_s {
#define SCSI_MAX_ALLOC_LEN 0xFF /* maximum allocarion length */
-#define SCSI_SENSE_CUR_ERR 0x70
-#define SCSI_SENSE_DEF_ERR 0x71
-
-/*
- * SCSI additional sense codes
- */
-#define SCSI_ASC_LUN_NOT_READY 0x04
-#define SCSI_ASC_LUN_NOT_SUPPORTED 0x25
-#define SCSI_ASC_TOCC 0x3F
-
-/*
- * SCSI additional sense code qualifiers
- */
-#define SCSI_ASCQ_MAN_INTR_REQ 0x03 /* manual intervention req */
-#define SCSI_ASCQ_RL_DATA_CHANGED 0x0E /* report luns data changed */
-
-/*
- * Methods of reporting informational exceptions
- */
-#define SCSI_MP_IEC_UNIT_ATTN 0x2 /* generate unit attention */
-
-struct scsi_report_luns_data_s {
- u32 lun_list_length; /* length of LUN list length */
- u32 reserved;
- struct scsi_lun lun[1]; /* first LUN in lun list */
-};
-
-struct scsi_inquiry_vendor_s {
- u8 vendor_id[8];
-};
-
-struct scsi_inquiry_prodid_s {
- u8 product_id[16];
-};
-
-struct scsi_inquiry_prodrev_s {
- u8 product_rev[4];
-};
-
-struct scsi_inquiry_data_s {
-#ifdef __BIG_ENDIAN
- u8 peripheral_qual:3; /* peripheral qualifier */
- u8 device_type:5; /* peripheral device type */
- u8 rmb:1; /* removable medium bit */
- u8 device_type_mod:7; /* device type modifier */
- u8 version;
- u8 aenc:1; /* async evt notification capability */
- u8 trm_iop:1; /* terminate I/O process */
- u8 norm_aca:1; /* normal ACA supported */
- u8 hi_support:1; /* SCSI-3: supports REPORT LUNS */
- u8 rsp_data_format:4;
- u8 additional_len;
- u8 sccs:1;
- u8 reserved1:7;
- u8 reserved2:1;
- u8 enc_serv:1; /* enclosure service component */
- u8 reserved3:1;
- u8 multi_port:1; /* multi-port device */
- u8 m_chngr:1; /* device in medium transport element */
- u8 ack_req_q:1; /* SIP specific bit */
- u8 addr32:1; /* SIP specific bit */
- u8 addr16:1; /* SIP specific bit */
- u8 rel_adr:1; /* relative address */
- u8 w_bus32:1;
- u8 w_bus16:1;
- u8 synchronous:1;
- u8 linked_commands:1;
- u8 trans_dis:1;
- u8 cmd_queue:1; /* command queueing supported */
- u8 soft_reset:1; /* soft reset alternative (VS) */
-#else
- u8 device_type:5; /* peripheral device type */
- u8 peripheral_qual:3; /* peripheral qualifier */
- u8 device_type_mod:7; /* device type modifier */
- u8 rmb:1; /* removable medium bit */
- u8 version;
- u8 rsp_data_format:4;
- u8 hi_support:1; /* SCSI-3: supports REPORT LUNS */
- u8 norm_aca:1; /* normal ACA supported */
- u8 terminate_iop:1;/* terminate I/O process */
- u8 aenc:1; /* async evt notification capability */
- u8 additional_len;
- u8 reserved1:7;
- u8 sccs:1;
- u8 addr16:1; /* SIP specific bit */
- u8 addr32:1; /* SIP specific bit */
- u8 ack_req_q:1; /* SIP specific bit */
- u8 m_chngr:1; /* device in medium transport element */
- u8 multi_port:1; /* multi-port device */
- u8 reserved3:1; /* TBD - Vendor Specific */
- u8 enc_serv:1; /* enclosure service component */
- u8 reserved2:1;
- u8 soft_seset:1; /* soft reset alternative (VS) */
- u8 cmd_queue:1; /* command queueing supported */
- u8 trans_dis:1;
- u8 linked_commands:1;
- u8 synchronous:1;
- u8 w_bus16:1;
- u8 w_bus32:1;
- u8 rel_adr:1; /* relative address */
-#endif
- struct scsi_inquiry_vendor_s vendor_id;
- struct scsi_inquiry_prodid_s product_id;
- struct scsi_inquiry_prodrev_s product_rev;
- u8 vendor_specific[20];
- u8 reserved4[40];
-};
-
-/*
- * SCSI sense data format
- */
-struct scsi_sense_s {
-#ifdef __BIG_ENDIAN
- u8 valid:1;
- u8 rsp_code:7;
-#else
- u8 rsp_code:7;
- u8 valid:1;
-#endif
- u8 seg_num;
-#ifdef __BIG_ENDIAN
- u8 file_mark:1;
- u8 eom:1; /* end of media */
- u8 ili:1; /* incorrect length indicator */
- u8 reserved:1;
- u8 sense_key:4;
-#else
- u8 sense_key:4;
- u8 reserved:1;
- u8 ili:1; /* incorrect length indicator */
- u8 eom:1; /* end of media */
- u8 file_mark:1;
-#endif
- u8 information[4]; /* device-type or cmd specific info */
- u8 add_sense_length; /* additional sense length */
- u8 command_info[4];/* command specific information */
- u8 asc; /* additional sense code */
- u8 ascq; /* additional sense code qualifier */
- u8 fru_code; /* field replaceable unit code */
-#ifdef __BIG_ENDIAN
- u8 sksv:1; /* sense key specific valid */
- u8 c_d:1; /* command/data bit */
- u8 res1:2;
- u8 bpv:1; /* bit pointer valid */
- u8 bpointer:3; /* bit pointer */
-#else
- u8 bpointer:3; /* bit pointer */
- u8 bpv:1; /* bit pointer valid */
- u8 res1:2;
- u8 c_d:1; /* command/data bit */
- u8 sksv:1; /* sense key specific valid */
-#endif
- u8 fpointer[2]; /* field pointer */
-};
-
/*
* Fibre Channel Header Structure (FCHS) definition
*/
diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c
index e07bd4745d8b..f0f80e282e39 100644
--- a/drivers/scsi/bfa/bfa_fcpim.c
+++ b/drivers/scsi/bfa/bfa_fcpim.c
@@ -24,8 +24,6 @@ BFA_TRC_FILE(HAL, FCPIM);
* BFA ITNIM Related definitions
*/
static void bfa_itnim_update_del_itn_stats(struct bfa_itnim_s *itnim);
-static bfa_boolean_t bfa_ioim_lm_proc_rpl_data(struct bfa_ioim_s *ioim);
-static bfa_boolean_t bfa_ioim_lm_proc_inq_data(struct bfa_ioim_s *ioim);
static void bfa_ioim_lm_init(struct bfa_s *bfa);
#define BFA_ITNIM_FROM_TAG(_fcpim, _tag) \
@@ -60,14 +58,6 @@ static void bfa_ioim_lm_init(struct bfa_s *bfa);
} \
} while (0)
-#define bfa_ioim_rp_wwn(__ioim) \
- (((struct bfa_fcs_rport_s *) \
- (__ioim)->itnim->rport->rport_drv)->pwwn)
-
-#define bfa_ioim_lp_wwn(__ioim) \
- ((BFA_LPS_FROM_TAG(BFA_LPS_MOD((__ioim)->bfa), \
- (__ioim)->itnim->rport->rport_info.lp_tag))->pwwn) \
-
#define bfa_itnim_sler_cb(__itnim) do { \
if ((__itnim)->bfa->fcs) \
bfa_cb_itnim_sler((__itnim)->ditn); \
@@ -77,13 +67,6 @@ static void bfa_ioim_lm_init(struct bfa_s *bfa);
} \
} while (0)
-enum bfa_ioim_lm_status {
- BFA_IOIM_LM_PRESENT = 1,
- BFA_IOIM_LM_LUN_NOT_SUP = 2,
- BFA_IOIM_LM_RPL_DATA_CHANGED = 3,
- BFA_IOIM_LM_LUN_NOT_RDY = 4,
-};
-
enum bfa_ioim_lm_ua_status {
BFA_IOIM_LM_UA_RESET = 0,
BFA_IOIM_LM_UA_SET = 1,
@@ -145,9 +128,6 @@ enum bfa_ioim_event {
BFA_IOIM_SM_TMDONE = 16, /* IO cleanup from tskim */
BFA_IOIM_SM_HWFAIL = 17, /* IOC h/w failure event */
BFA_IOIM_SM_IOTOV = 18, /* ITN offline TOV */
- BFA_IOIM_SM_LM_LUN_NOT_SUP = 19,/* lunmask lun not supported */
- BFA_IOIM_SM_LM_RPL_DC = 20, /* lunmask report-lun data changed */
- BFA_IOIM_SM_LM_LUN_NOT_RDY = 21,/* lunmask lun not ready */
};
@@ -245,9 +225,6 @@ static void __bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete);
static void __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete);
static void __bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete);
static bfa_boolean_t bfa_ioim_is_abortable(struct bfa_ioim_s *ioim);
-static void __bfa_cb_ioim_lm_lun_not_sup(void *cbarg, bfa_boolean_t complete);
-static void __bfa_cb_ioim_lm_rpl_dc(void *cbarg, bfa_boolean_t complete);
-static void __bfa_cb_ioim_lm_lun_not_rdy(void *cbarg, bfa_boolean_t complete);
/*
* forward declaration of BFA IO state machine
@@ -445,12 +422,6 @@ bfa_fcpim_add_stats(struct bfa_itnim_iostats_s *lstats,
bfa_fcpim_add_iostats(lstats, rstats, output_reqs);
bfa_fcpim_add_iostats(lstats, rstats, rd_throughput);
bfa_fcpim_add_iostats(lstats, rstats, wr_throughput);
- bfa_fcpim_add_iostats(lstats, rstats, lm_lun_across_sg);
- bfa_fcpim_add_iostats(lstats, rstats, lm_lun_not_sup);
- bfa_fcpim_add_iostats(lstats, rstats, lm_rpl_data_changed);
- bfa_fcpim_add_iostats(lstats, rstats, lm_wire_residue_changed);
- bfa_fcpim_add_iostats(lstats, rstats, lm_small_buf_addresidue);
- bfa_fcpim_add_iostats(lstats, rstats, lm_lun_not_rdy);
}
bfa_status_t
@@ -1580,27 +1551,6 @@ bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event)
__bfa_cb_ioim_abort, ioim);
break;
- case BFA_IOIM_SM_LM_LUN_NOT_SUP:
- bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
- bfa_ioim_move_to_comp_q(ioim);
- bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
- __bfa_cb_ioim_lm_lun_not_sup, ioim);
- break;
-
- case BFA_IOIM_SM_LM_RPL_DC:
- bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
- bfa_ioim_move_to_comp_q(ioim);
- bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
- __bfa_cb_ioim_lm_rpl_dc, ioim);
- break;
-
- case BFA_IOIM_SM_LM_LUN_NOT_RDY:
- bfa_sm_set_state(ioim, bfa_ioim_sm_hcb);
- bfa_ioim_move_to_comp_q(ioim);
- bfa_cb_queue(ioim->bfa, &ioim->hcb_qe,
- __bfa_cb_ioim_lm_lun_not_rdy, ioim);
- break;
-
default:
bfa_sm_fault(ioim->bfa, event);
}
@@ -2160,243 +2110,6 @@ bfa_ioim_lm_init(struct bfa_s *bfa)
}
}
-/*
- * Validate LUN for LUN masking
- */
-static enum bfa_ioim_lm_status
-bfa_ioim_lm_check(struct bfa_ioim_s *ioim, struct bfa_lps_s *lps,
- struct bfa_rport_s *rp, struct scsi_lun lun)
-{
- u8 i;
- struct bfa_lun_mask_s *lun_list = bfa_get_lun_mask_list(ioim->bfa);
- struct scsi_cmnd *cmnd = (struct scsi_cmnd *)ioim->dio;
- struct scsi_cdb_s *cdb = (struct scsi_cdb_s *)cmnd->cmnd;
-
- if ((cdb->scsi_cdb[0] == REPORT_LUNS) &&
- (scsilun_to_int((struct scsi_lun *)&lun) == 0)) {
- ioim->proc_rsp_data = bfa_ioim_lm_proc_rpl_data;
- return BFA_IOIM_LM_PRESENT;
- }
-
- for (i = 0; i < MAX_LUN_MASK_CFG; i++) {
-
- if (lun_list[i].state != BFA_IOIM_LUN_MASK_ACTIVE)
- continue;
-
- if ((scsilun_to_int((struct scsi_lun *)&lun_list[i].lun) ==
- scsilun_to_int((struct scsi_lun *)&lun))
- && (rp->rport_tag == lun_list[i].rp_tag)
- && ((u8)ioim->itnim->rport->rport_info.lp_tag ==
- lun_list[i].lp_tag)) {
- bfa_trc(ioim->bfa, lun_list[i].rp_tag);
- bfa_trc(ioim->bfa, lun_list[i].lp_tag);
- bfa_trc(ioim->bfa, scsilun_to_int(
- (struct scsi_lun *)&lun_list[i].lun));
-
- if ((lun_list[i].ua == BFA_IOIM_LM_UA_SET) &&
- ((cdb->scsi_cdb[0] != INQUIRY) ||
- (cdb->scsi_cdb[0] != REPORT_LUNS))) {
- lun_list[i].ua = BFA_IOIM_LM_UA_RESET;
- return BFA_IOIM_LM_RPL_DATA_CHANGED;
- }
-
- if (cdb->scsi_cdb[0] == REPORT_LUNS)
- ioim->proc_rsp_data = bfa_ioim_lm_proc_rpl_data;
-
- return BFA_IOIM_LM_PRESENT;
- }
- }
-
- if ((cdb->scsi_cdb[0] == INQUIRY) &&
- (scsilun_to_int((struct scsi_lun *)&lun) == 0)) {
- ioim->proc_rsp_data = bfa_ioim_lm_proc_inq_data;
- return BFA_IOIM_LM_PRESENT;
- }
-
- if (cdb->scsi_cdb[0] == TEST_UNIT_READY)
- return BFA_IOIM_LM_LUN_NOT_RDY;
-
- return BFA_IOIM_LM_LUN_NOT_SUP;
-}
-
-static bfa_boolean_t
-bfa_ioim_lm_proc_rsp_data_dummy(struct bfa_ioim_s *ioim)
-{
- return BFA_TRUE;
-}
-
-static void
-bfa_ioim_lm_fetch_lun(struct bfa_ioim_s *ioim, u8 *rl_data, int offset,
- int buf_lun_cnt)
-{
- struct bfa_lun_mask_s *lun_list = bfa_get_lun_mask_list(ioim->bfa);
- struct scsi_lun *lun_data = (struct scsi_lun *)(rl_data + offset);
- struct scsi_lun lun;
- int i, j;
-
- bfa_trc(ioim->bfa, buf_lun_cnt);
- for (j = 0; j < buf_lun_cnt; j++) {
- lun = *((struct scsi_lun *)(lun_data + j));
- for (i = 0; i < MAX_LUN_MASK_CFG; i++) {
- if (lun_list[i].state != BFA_IOIM_LUN_MASK_ACTIVE)
- continue;
- if ((lun_list[i].rp_wwn == bfa_ioim_rp_wwn(ioim)) &&
- (lun_list[i].lp_wwn == bfa_ioim_lp_wwn(ioim)) &&
- (scsilun_to_int((struct scsi_lun *)&lun_list[i].lun)
- == scsilun_to_int((struct scsi_lun *)&lun))) {
- lun_list[i].state = BFA_IOIM_LUN_MASK_FETCHED;
- break;
- }
- } /* next lun in mask DB */
- } /* next lun in buf */
-}
-
-static int
-bfa_ioim_lm_update_lun_sg(struct bfa_ioim_s *ioim, u32 *pgdlen,
- struct scsi_report_luns_data_s *rl)
-{
- struct scsi_cmnd *cmnd = (struct scsi_cmnd *)ioim->dio;
- struct scatterlist *sg = scsi_sglist(cmnd);
- struct bfa_lun_mask_s *lun_list = bfa_get_lun_mask_list(ioim->bfa);
- struct scsi_lun *prev_rl_data = NULL, *base_rl_data;
- int i, j, sgeid, lun_fetched_cnt = 0, prev_sg_len = 0, base_count;
- int lun_across_sg_bytes, bytes_from_next_buf;
- u64 last_lun, temp_last_lun;
-
- /* fetch luns from the first sg element */
- bfa_ioim_lm_fetch_lun(ioim, (u8 *)(rl->lun), 0,
- (sg_dma_len(sg) / sizeof(struct scsi_lun)) - 1);
-
- /* fetch luns from multiple sg elements */
- scsi_for_each_sg(cmnd, sg, scsi_sg_count(cmnd), sgeid) {
- if (sgeid == 0) {
- prev_sg_len = sg_dma_len(sg);
- prev_rl_data = (struct scsi_lun *)
- phys_to_virt(sg_dma_address(sg));
- continue;
- }
-
- /* if the buf is having more data */
- lun_across_sg_bytes = prev_sg_len % sizeof(struct scsi_lun);
- if (lun_across_sg_bytes) {
- bfa_trc(ioim->bfa, lun_across_sg_bytes);
- bfa_stats(ioim->itnim, lm_lun_across_sg);
- bytes_from_next_buf = sizeof(struct scsi_lun) -
- lun_across_sg_bytes;
-
- /* from next buf take higher bytes */
- temp_last_lun = *((u64 *)
- phys_to_virt(sg_dma_address(sg)));
- last_lun |= temp_last_lun >>
- (lun_across_sg_bytes * BITS_PER_BYTE);
-
- /* from prev buf take higher bytes */
- temp_last_lun = *((u64 *)(prev_rl_data +
- (prev_sg_len - lun_across_sg_bytes)));
- temp_last_lun >>= bytes_from_next_buf * BITS_PER_BYTE;
- last_lun = last_lun | (temp_last_lun <<
- (bytes_from_next_buf * BITS_PER_BYTE));
-
- bfa_ioim_lm_fetch_lun(ioim, (u8 *)&last_lun, 0, 1);
- } else
- bytes_from_next_buf = 0;
-
- *pgdlen += sg_dma_len(sg);
- prev_sg_len = sg_dma_len(sg);
- prev_rl_data = (struct scsi_lun *)
- phys_to_virt(sg_dma_address(sg));
- bfa_ioim_lm_fetch_lun(ioim, (u8 *)prev_rl_data,
- bytes_from_next_buf,
- sg_dma_len(sg) / sizeof(struct scsi_lun));
- }
-
- /* update the report luns data - based on fetched luns */
- sg = scsi_sglist(cmnd);
- base_rl_data = (struct scsi_lun *)rl->lun;
- base_count = (sg_dma_len(sg) / sizeof(struct scsi_lun)) - 1;
- for (i = 0, j = 0; i < MAX_LUN_MASK_CFG; i++) {
- if (lun_list[i].state == BFA_IOIM_LUN_MASK_FETCHED) {
- base_rl_data[j] = lun_list[i].lun;
- lun_list[i].state = BFA_IOIM_LUN_MASK_ACTIVE;
- j++;
- lun_fetched_cnt++;
- }
-
- if (j > base_count) {
- j = 0;
- sg = sg_next(sg);
- base_rl_data = (struct scsi_lun *)
- phys_to_virt(sg_dma_address(sg));
- base_count = sg_dma_len(sg) / sizeof(struct scsi_lun);
- }
- }
-
- bfa_trc(ioim->bfa, lun_fetched_cnt);
- return lun_fetched_cnt;
-}
-
-static bfa_boolean_t
-bfa_ioim_lm_proc_inq_data(struct bfa_ioim_s *ioim)
-{
- struct scsi_inquiry_data_s *inq;
- struct scatterlist *sg = scsi_sglist((struct scsi_cmnd *)ioim->dio);
-
- ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy;
- inq = (struct scsi_inquiry_data_s *)phys_to_virt(sg_dma_address(sg));
-
- bfa_trc(ioim->bfa, inq->device_type);
- inq->peripheral_qual = SCSI_INQ_PQ_NOT_CON;
- return 0;
-}
-
-static bfa_boolean_t
-bfa_ioim_lm_proc_rpl_data(struct bfa_ioim_s *ioim)
-{
- struct scsi_cmnd *cmnd = (struct scsi_cmnd *)ioim->dio;
- struct scatterlist *sg = scsi_sglist(cmnd);
- struct bfi_ioim_rsp_s *m;
- struct scsi_report_luns_data_s *rl = NULL;
- int lun_count = 0, lun_fetched_cnt = 0;
- u32 residue, pgdlen = 0;
-
- ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy;
- if (bfa_get_lun_mask_status(ioim->bfa) != BFA_LUNMASK_ENABLED)
- return BFA_TRUE;
-
- m = (struct bfi_ioim_rsp_s *) &ioim->iosp->comp_rspmsg;
- if (m->scsi_status == SCSI_STATUS_CHECK_CONDITION)
- return BFA_TRUE;
-
- pgdlen = sg_dma_len(sg);
- bfa_trc(ioim->bfa, pgdlen);
- rl = (struct scsi_report_luns_data_s *)phys_to_virt(sg_dma_address(sg));
- lun_count = cpu_to_be32(rl->lun_list_length) / sizeof(struct scsi_lun);
- lun_fetched_cnt = bfa_ioim_lm_update_lun_sg(ioim, &pgdlen, rl);
-
- if (lun_count == lun_fetched_cnt)
- return BFA_TRUE;
-
- bfa_trc(ioim->bfa, lun_count);
- bfa_trc(ioim->bfa, lun_fetched_cnt);
- bfa_trc(ioim->bfa, be32_to_cpu(rl->lun_list_length));
-
- if (be32_to_cpu(rl->lun_list_length) <= pgdlen)
- rl->lun_list_length = be32_to_cpu(lun_fetched_cnt) *
- sizeof(struct scsi_lun);
- else
- bfa_stats(ioim->itnim, lm_small_buf_addresidue);
-
- bfa_trc(ioim->bfa, be32_to_cpu(rl->lun_list_length));
- bfa_trc(ioim->bfa, be32_to_cpu(m->residue));
-
- residue = be32_to_cpu(m->residue);
- residue += (lun_count - lun_fetched_cnt) * sizeof(struct scsi_lun);
- bfa_stats(ioim->itnim, lm_wire_residue_changed);
- m->residue = be32_to_cpu(residue);
- bfa_trc(ioim->bfa, ioim->nsges);
- return BFA_FALSE;
-}
-
static void
__bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete)
{
@@ -2454,83 +2167,6 @@ __bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete)
m->scsi_status, sns_len, snsinfo, residue);
}
-static void
-__bfa_cb_ioim_lm_lun_not_sup(void *cbarg, bfa_boolean_t complete)
-{
- struct bfa_ioim_s *ioim = cbarg;
- int sns_len = 0xD;
- u32 residue = scsi_bufflen((struct scsi_cmnd *)ioim->dio);
- struct scsi_sense_s *snsinfo;
-
- if (!complete) {
- bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
- return;
- }
-
- snsinfo = (struct scsi_sense_s *)BFA_SNSINFO_FROM_TAG(
- ioim->fcpim->fcp, ioim->iotag);
- snsinfo->rsp_code = SCSI_SENSE_CUR_ERR;
- snsinfo->add_sense_length = 0xa;
- snsinfo->asc = SCSI_ASC_LUN_NOT_SUPPORTED;
- snsinfo->sense_key = ILLEGAL_REQUEST;
- bfa_trc(ioim->bfa, residue);
- bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_OK,
- SCSI_STATUS_CHECK_CONDITION, sns_len,
- (u8 *)snsinfo, residue);
-}
-
-static void
-__bfa_cb_ioim_lm_rpl_dc(void *cbarg, bfa_boolean_t complete)
-{
- struct bfa_ioim_s *ioim = cbarg;
- int sns_len = 0xD;
- u32 residue = scsi_bufflen((struct scsi_cmnd *)ioim->dio);
- struct scsi_sense_s *snsinfo;
-
- if (!complete) {
- bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
- return;
- }
-
- snsinfo = (struct scsi_sense_s *)BFA_SNSINFO_FROM_TAG(ioim->fcpim->fcp,
- ioim->iotag);
- snsinfo->rsp_code = SCSI_SENSE_CUR_ERR;
- snsinfo->sense_key = SCSI_MP_IEC_UNIT_ATTN;
- snsinfo->asc = SCSI_ASC_TOCC;
- snsinfo->add_sense_length = 0x6;
- snsinfo->ascq = SCSI_ASCQ_RL_DATA_CHANGED;
- bfa_trc(ioim->bfa, residue);
- bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_OK,
- SCSI_STATUS_CHECK_CONDITION, sns_len,
- (u8 *)snsinfo, residue);
-}
-
-static void
-__bfa_cb_ioim_lm_lun_not_rdy(void *cbarg, bfa_boolean_t complete)
-{
- struct bfa_ioim_s *ioim = cbarg;
- int sns_len = 0xD;
- u32 residue = scsi_bufflen((struct scsi_cmnd *)ioim->dio);
- struct scsi_sense_s *snsinfo;
-
- if (!complete) {
- bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB);
- return;
- }
-
- snsinfo = (struct scsi_sense_s *)BFA_SNSINFO_FROM_TAG(
- ioim->fcpim->fcp, ioim->iotag);
- snsinfo->rsp_code = SCSI_SENSE_CUR_ERR;
- snsinfo->add_sense_length = 0xa;
- snsinfo->sense_key = NOT_READY;
- snsinfo->asc = SCSI_ASC_LUN_NOT_READY;
- snsinfo->ascq = SCSI_ASCQ_MAN_INTR_REQ;
- bfa_trc(ioim->bfa, residue);
- bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_OK,
- SCSI_STATUS_CHECK_CONDITION, sns_len,
- (u8 *)snsinfo, residue);
-}
-
void
bfa_fcpim_lunmask_rp_update(struct bfa_s *bfa, wwn_t lp_wwn, wwn_t rp_wwn,
u16 rp_tag, u8 lp_tag)
@@ -2647,7 +2283,8 @@ bfa_fcpim_lunmask_add(struct bfa_s *bfa, u16 vf_id, wwn_t *pwwn,
if (port) {
*pwwn = port->port_cfg.pwwn;
rp_fcs = bfa_fcs_lport_get_rport_by_pwwn(port, rpwwn);
- rp = rp_fcs->bfa_rport;
+ if (rp_fcs)
+ rp = rp_fcs->bfa_rport;
}
lunm_list = bfa_get_lun_mask_list(bfa);
@@ -2715,7 +2352,8 @@ bfa_fcpim_lunmask_delete(struct bfa_s *bfa, u16 vf_id, wwn_t *pwwn,
if (port) {
*pwwn = port->port_cfg.pwwn;
rp_fcs = bfa_fcs_lport_get_rport_by_pwwn(port, rpwwn);
- rp = rp_fcs->bfa_rport;
+ if (rp_fcs)
+ rp = rp_fcs->bfa_rport;
}
}
@@ -2757,7 +2395,6 @@ __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete)
return;
}
- ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy;
bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_ABORTED,
0, 0, NULL, 0);
}
@@ -2773,7 +2410,6 @@ __bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete)
return;
}
- ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy;
bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_PATHTOV,
0, 0, NULL, 0);
}
@@ -2788,7 +2424,6 @@ __bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete)
return;
}
- ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy;
bfa_cb_ioim_abort(ioim->bfa->bfad, ioim->dio);
}
@@ -3132,7 +2767,6 @@ bfa_ioim_attach(struct bfa_fcpim_s *fcpim)
ioim->bfa = fcpim->bfa;
ioim->fcpim = fcpim;
ioim->iosp = iosp;
- ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy;
INIT_LIST_HEAD(&ioim->sgpg_q);
bfa_reqq_winit(&ioim->iosp->reqq_wait,
bfa_ioim_qresume, ioim);
@@ -3170,7 +2804,6 @@ bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
evt = BFA_IOIM_SM_DONE;
else
evt = BFA_IOIM_SM_COMP;
- ioim->proc_rsp_data(ioim);
break;
case BFI_IOIM_STS_TIMEDOUT:
@@ -3206,7 +2839,6 @@ bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
if (rsp->abort_tag != ioim->abort_tag) {
bfa_trc(ioim->bfa, rsp->abort_tag);
bfa_trc(ioim->bfa, ioim->abort_tag);
- ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy;
return;
}
@@ -3225,7 +2857,6 @@ bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
WARN_ON(1);
}
- ioim->proc_rsp_data = bfa_ioim_lm_proc_rsp_data_dummy;
bfa_sm_send_event(ioim, evt);
}
@@ -3244,15 +2875,7 @@ bfa_ioim_good_comp_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
bfa_ioim_cb_profile_comp(fcpim, ioim);
- if (bfa_get_lun_mask_status(bfa) != BFA_LUNMASK_ENABLED) {
- bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD);
- return;
- }
-
- if (ioim->proc_rsp_data(ioim) == BFA_TRUE)
- bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD);
- else
- bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP);
+ bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD);
}
/*
@@ -3364,35 +2987,6 @@ bfa_ioim_free(struct bfa_ioim_s *ioim)
void
bfa_ioim_start(struct bfa_ioim_s *ioim)
{
- struct scsi_cmnd *cmnd = (struct scsi_cmnd *)ioim->dio;
- struct bfa_lps_s *lps;
- enum bfa_ioim_lm_status status;
- struct scsi_lun scsilun;
-
- if (bfa_get_lun_mask_status(ioim->bfa) == BFA_LUNMASK_ENABLED) {
- lps = BFA_IOIM_TO_LPS(ioim);
- int_to_scsilun(cmnd->device->lun, &scsilun);
- status = bfa_ioim_lm_check(ioim, lps,
- ioim->itnim->rport, scsilun);
- if (status == BFA_IOIM_LM_LUN_NOT_RDY) {
- bfa_sm_send_event(ioim, BFA_IOIM_SM_LM_LUN_NOT_RDY);
- bfa_stats(ioim->itnim, lm_lun_not_rdy);
- return;
- }
-
- if (status == BFA_IOIM_LM_LUN_NOT_SUP) {
- bfa_sm_send_event(ioim, BFA_IOIM_SM_LM_LUN_NOT_SUP);
- bfa_stats(ioim->itnim, lm_lun_not_sup);
- return;
- }
-
- if (status == BFA_IOIM_LM_RPL_DATA_CHANGED) {
- bfa_sm_send_event(ioim, BFA_IOIM_SM_LM_RPL_DC);
- bfa_stats(ioim->itnim, lm_rpl_data_changed);
- return;
- }
- }
-
bfa_ioim_cb_profile_start(ioim->fcpim, ioim);
/*
diff --git a/drivers/scsi/bfa/bfa_fcpim.h b/drivers/scsi/bfa/bfa_fcpim.h
index 1080bcb81cb7..36f26da80f76 100644
--- a/drivers/scsi/bfa/bfa_fcpim.h
+++ b/drivers/scsi/bfa/bfa_fcpim.h
@@ -110,7 +110,6 @@ struct bfad_ioim_s;
struct bfad_tskim_s;
typedef void (*bfa_fcpim_profile_t) (struct bfa_ioim_s *ioim);
-typedef bfa_boolean_t (*bfa_ioim_lm_proc_rsp_data_t) (struct bfa_ioim_s *ioim);
struct bfa_fcpim_s {
struct bfa_s *bfa;
@@ -124,7 +123,6 @@ struct bfa_fcpim_s {
u32 path_tov;
u16 q_depth;
u8 reqq; /* Request queue to be used */
- u8 lun_masking_pending;
struct list_head itnim_q; /* queue of active itnim */
struct list_head ioim_resfree_q; /* IOs waiting for f/w */
struct list_head ioim_comp_q; /* IO global comp Q */
@@ -181,7 +179,6 @@ struct bfa_ioim_s {
u8 reqq; /* Request queue for I/O */
u8 mode; /* IO is passthrough or not */
u64 start_time; /* IO's Profile start val */
- bfa_ioim_lm_proc_rsp_data_t proc_rsp_data; /* RSP data adjust */
};
struct bfa_ioim_sp_s {
@@ -261,10 +258,6 @@ struct bfa_itnim_s {
(__ioim)->iotag |= k << BFA_IOIM_RETRY_TAG_OFFSET; \
} while (0)
-#define BFA_IOIM_TO_LPS(__ioim) \
- BFA_LPS_FROM_TAG(BFA_LPS_MOD(__ioim->bfa), \
- __ioim->itnim->rport->rport_info.lp_tag)
-
static inline bfa_boolean_t
bfa_ioim_maxretry_reached(struct bfa_ioim_s *ioim)
{
diff --git a/drivers/scsi/bfa/bfa_svc.h b/drivers/scsi/bfa/bfa_svc.h
index 95adb86d3769..b52cbb6bcd5a 100644
--- a/drivers/scsi/bfa/bfa_svc.h
+++ b/drivers/scsi/bfa/bfa_svc.h
@@ -582,11 +582,6 @@ void bfa_cb_rport_qos_scn_prio(void *rport,
#define BFA_LP_TAG_INVALID 0xff
void bfa_rport_set_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp);
void bfa_rport_unset_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp);
-bfa_boolean_t bfa_rport_lunmask_active(struct bfa_rport_s *rp);
-wwn_t bfa_rport_get_pwwn(struct bfa_s *bfa, struct bfa_rport_s *rp);
-struct bfa_rport_s *bfa_rport_get_by_wwn(struct bfa_s *bfa, u16 vf_id,
- wwn_t *lpwwn, wwn_t rpwwn);
-void *bfa_cb_get_rp_by_wwn(void *arg, u16 vf_id, wwn_t *lpwwn, wwn_t rpwwn);
/*
* bfa fcxp API functions
diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c
index 66fb72531b34..404fd10ddb21 100644
--- a/drivers/scsi/bfa/bfad.c
+++ b/drivers/scsi/bfa/bfad.c
@@ -674,6 +674,7 @@ bfad_vport_create(struct bfad_s *bfad, u16 vf_id,
spin_lock_irqsave(&bfad->bfad_lock, flags);
bfa_fcs_vport_start(&vport->fcs_vport);
+ list_add_tail(&vport->list_entry, &bfad->vport_list);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
return BFA_STATUS_OK;
@@ -1404,6 +1405,7 @@ bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
bfad->ref_count = 0;
bfad->pport.bfad = bfad;
INIT_LIST_HEAD(&bfad->pbc_vport_list);
+ INIT_LIST_HEAD(&bfad->vport_list);
/* Setup the debugfs node for this bfad */
if (bfa_debugfs_enable)
diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c
index 9d95844ab463..1938fe0473e9 100644
--- a/drivers/scsi/bfa/bfad_attr.c
+++ b/drivers/scsi/bfa/bfad_attr.c
@@ -491,7 +491,7 @@ bfad_im_vport_delete(struct fc_vport *fc_vport)
free_scsi_host:
bfad_scsi_host_free(bfad, im_port);
-
+ list_del(&vport->list_entry);
kfree(vport);
return 0;
diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c
index 06fc00caeb41..530de2b1200a 100644
--- a/drivers/scsi/bfa/bfad_bsg.c
+++ b/drivers/scsi/bfa/bfad_bsg.c
@@ -2394,6 +2394,21 @@ out:
return 0;
}
+/* Function to reset the LUN SCAN mode */
+static void
+bfad_iocmd_lunmask_reset_lunscan_mode(struct bfad_s *bfad, int lunmask_cfg)
+{
+ struct bfad_im_port_s *pport_im = bfad->pport.im_port;
+ struct bfad_vport_s *vport = NULL;
+
+ /* Set the scsi device LUN SCAN flags for base port */
+ bfad_reset_sdev_bflags(pport_im, lunmask_cfg);
+
+ /* Set the scsi device LUN SCAN flags for the vports */
+ list_for_each_entry(vport, &bfad->vport_list, list_entry)
+ bfad_reset_sdev_bflags(vport->drv_port.im_port, lunmask_cfg);
+}
+
int
bfad_iocmd_lunmask(struct bfad_s *bfad, void *pcmd, unsigned int v_cmd)
{
@@ -2401,11 +2416,17 @@ bfad_iocmd_lunmask(struct bfad_s *bfad, void *pcmd, unsigned int v_cmd)
unsigned long flags;
spin_lock_irqsave(&bfad->bfad_lock, flags);
- if (v_cmd == IOCMD_FCPIM_LUNMASK_ENABLE)
+ if (v_cmd == IOCMD_FCPIM_LUNMASK_ENABLE) {
iocmd->status = bfa_fcpim_lunmask_update(&bfad->bfa, BFA_TRUE);
- else if (v_cmd == IOCMD_FCPIM_LUNMASK_DISABLE)
+ /* Set the LUN Scanning mode to be Sequential scan */
+ if (iocmd->status == BFA_STATUS_OK)
+ bfad_iocmd_lunmask_reset_lunscan_mode(bfad, BFA_TRUE);
+ } else if (v_cmd == IOCMD_FCPIM_LUNMASK_DISABLE) {
iocmd->status = bfa_fcpim_lunmask_update(&bfad->bfa, BFA_FALSE);
- else if (v_cmd == IOCMD_FCPIM_LUNMASK_CLEAR)
+ /* Set the LUN Scanning mode to default REPORT_LUNS scan */
+ if (iocmd->status == BFA_STATUS_OK)
+ bfad_iocmd_lunmask_reset_lunscan_mode(bfad, BFA_FALSE);
+ } else if (v_cmd == IOCMD_FCPIM_LUNMASK_CLEAR)
iocmd->status = bfa_fcpim_lunmask_clear(&bfad->bfa);
spin_unlock_irqrestore(&bfad->bfad_lock, flags);
return 0;
diff --git a/drivers/scsi/bfa/bfad_drv.h b/drivers/scsi/bfa/bfad_drv.h
index 5e19a5f820ec..dc5b9d99c450 100644
--- a/drivers/scsi/bfa/bfad_drv.h
+++ b/drivers/scsi/bfa/bfad_drv.h
@@ -43,6 +43,7 @@
#include <scsi/scsi_transport_fc.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_bsg_fc.h>
+#include <scsi/scsi_devinfo.h>
#include "bfa_modules.h"
#include "bfa_fcs.h"
@@ -227,6 +228,7 @@ struct bfad_s {
struct list_head active_aen_q;
struct bfa_aen_entry_s aen_list[BFA_AEN_MAX_ENTRY];
spinlock_t bfad_aen_spinlock;
+ struct list_head vport_list;
};
/* BFAD state machine events */
diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c
index e5db649e8eb7..3153923f5b60 100644
--- a/drivers/scsi/bfa/bfad_im.c
+++ b/drivers/scsi/bfa/bfad_im.c
@@ -918,16 +918,70 @@ bfad_get_itnim(struct bfad_im_port_s *im_port, int id)
}
/*
+ * Function is invoked from the SCSI Host Template slave_alloc() entry point.
+ * Has the logic to query the LUN Mask database to check if this LUN needs to
+ * be made visible to the SCSI mid-layer or not.
+ *
+ * Returns BFA_STATUS_OK if this LUN needs to be added to the OS stack.
+ * Returns -ENXIO to notify SCSI mid-layer to not add this LUN to the OS stack.
+ */
+static int
+bfad_im_check_if_make_lun_visible(struct scsi_device *sdev,
+ struct fc_rport *rport)
+{
+ struct bfad_itnim_data_s *itnim_data =
+ (struct bfad_itnim_data_s *) rport->dd_data;
+ struct bfa_s *bfa = itnim_data->itnim->bfa_itnim->bfa;
+ struct bfa_rport_s *bfa_rport = itnim_data->itnim->bfa_itnim->rport;
+ struct bfa_lun_mask_s *lun_list = bfa_get_lun_mask_list(bfa);
+ int i = 0, ret = -ENXIO;
+
+ for (i = 0; i < MAX_LUN_MASK_CFG; i++) {
+ if (lun_list[i].state == BFA_IOIM_LUN_MASK_ACTIVE &&
+ scsilun_to_int(&lun_list[i].lun) == sdev->lun &&
+ lun_list[i].rp_tag == bfa_rport->rport_tag &&
+ lun_list[i].lp_tag == (u8)bfa_rport->rport_info.lp_tag) {
+ ret = BFA_STATUS_OK;
+ break;
+ }
+ }
+ return ret;
+}
+
+/*
* Scsi_Host template entry slave_alloc
*/
static int
bfad_im_slave_alloc(struct scsi_device *sdev)
{
struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
+ struct bfad_itnim_data_s *itnim_data =
+ (struct bfad_itnim_data_s *) rport->dd_data;
+ struct bfa_s *bfa = itnim_data->itnim->bfa_itnim->bfa;
if (!rport || fc_remote_port_chkready(rport))
return -ENXIO;
+ if (bfa_get_lun_mask_status(bfa) == BFA_LUNMASK_ENABLED) {
+ /*
+ * We should not mask LUN 0 - since this will translate
+ * to no LUN / TARGET for SCSI ml resulting no scan.
+ */
+ if (sdev->lun == 0) {
+ sdev->sdev_bflags |= BLIST_NOREPORTLUN |
+ BLIST_SPARSELUN;
+ goto done;
+ }
+
+ /*
+ * Query LUN Mask configuration - to expose this LUN
+ * to the SCSI mid-layer or to mask it.
+ */
+ if (bfad_im_check_if_make_lun_visible(sdev, rport) !=
+ BFA_STATUS_OK)
+ return -ENXIO;
+ }
+done:
sdev->hostdata = rport->dd_data;
return 0;
@@ -1037,6 +1091,8 @@ bfad_im_fc_rport_add(struct bfad_im_port_s *im_port, struct bfad_itnim_s *itnim)
&& (fc_rport->scsi_target_id < MAX_FCP_TARGET))
itnim->scsi_tgt_id = fc_rport->scsi_target_id;
+ itnim->channel = fc_rport->channel;
+
return;
}
diff --git a/drivers/scsi/bfa/bfad_im.h b/drivers/scsi/bfa/bfad_im.h
index 004b6cf848d9..0814367ef101 100644
--- a/drivers/scsi/bfa/bfad_im.h
+++ b/drivers/scsi/bfa/bfad_im.h
@@ -91,6 +91,7 @@ struct bfad_itnim_s {
struct fc_rport *fc_rport;
struct bfa_itnim_s *bfa_itnim;
u16 scsi_tgt_id;
+ u16 channel;
u16 queue_work;
unsigned long last_ramp_up_time;
unsigned long last_queue_full_time;
@@ -166,4 +167,30 @@ irqreturn_t bfad_intx(int irq, void *dev_id);
int bfad_im_bsg_request(struct fc_bsg_job *job);
int bfad_im_bsg_timeout(struct fc_bsg_job *job);
+/*
+ * Macro to set the SCSI device sdev_bflags - sdev_bflags are used by the
+ * SCSI mid-layer to choose LUN Scanning mode REPORT_LUNS vs. Sequential Scan
+ *
+ * Internally iterate's over all the ITNIM's part of the im_port & set's the
+ * sdev_bflags for the scsi_device associated with LUN #0.
+ */
+#define bfad_reset_sdev_bflags(__im_port, __lunmask_cfg) do { \
+ struct scsi_device *__sdev = NULL; \
+ struct bfad_itnim_s *__itnim = NULL; \
+ u32 scan_flags = BLIST_NOREPORTLUN | BLIST_SPARSELUN; \
+ list_for_each_entry(__itnim, &((__im_port)->itnim_mapped_list), \
+ list_entry) { \
+ __sdev = scsi_device_lookup((__im_port)->shost, \
+ __itnim->channel, \
+ __itnim->scsi_tgt_id, 0); \
+ if (__sdev) { \
+ if ((__lunmask_cfg) == BFA_TRUE) \
+ __sdev->sdev_bflags |= scan_flags; \
+ else \
+ __sdev->sdev_bflags &= ~scan_flags; \
+ scsi_device_put(__sdev); \
+ } \
+ } \
+} while (0)
+
#endif
diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c
index c5360ffb4bed..d3ff9cd40234 100644
--- a/drivers/scsi/cxgbi/libcxgbi.c
+++ b/drivers/scsi/cxgbi/libcxgbi.c
@@ -1868,8 +1868,9 @@ int cxgbi_conn_alloc_pdu(struct iscsi_task *task, u8 opcode)
tdata->skb = alloc_skb(cdev->skb_tx_rsvd + headroom, GFP_ATOMIC);
if (!tdata->skb) {
- pr_warn("alloc skb %u+%u, opcode 0x%x failed.\n",
- cdev->skb_tx_rsvd, headroom, opcode);
+ struct cxgbi_sock *csk = cconn->cep->csk;
+ struct net_device *ndev = cdev->ports[csk->port_id];
+ ndev->stats.tx_dropped++;
return -ENOMEM;
}
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index f5b718d3c31b..13aeca3d51f2 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/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c
index 4ef021291a4d..04c5cea47a22 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -466,6 +466,11 @@ static int alua_check_sense(struct scsi_device *sdev,
* Power On, Reset, or Bus Device Reset, just retry.
*/
return ADD_TO_MLQUEUE;
+ if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x01)
+ /*
+ * Mode Parameters Changed
+ */
+ return ADD_TO_MLQUEUE;
if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x06)
/*
* ALUA state changed
diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c
index 841ebf4a6788..53a31c753cb1 100644
--- a/drivers/scsi/device_handler/scsi_dh_rdac.c
+++ b/drivers/scsi/device_handler/scsi_dh_rdac.c
@@ -953,6 +953,8 @@ static int __init rdac_init(void)
if (!kmpath_rdacd) {
scsi_unregister_device_handler(&rdac_dh);
printk(KERN_ERR "kmpath_rdacd creation failed.\n");
+
+ r = -EINVAL;
}
done:
return r;
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 8d67467dd9ce..e9599600aa23 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -58,7 +58,11 @@ module_param_named(ddp_min, fcoe_ddp_min, uint, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(ddp_min, "Minimum I/O size in bytes for " \
"Direct Data Placement (DDP).");
-DEFINE_MUTEX(fcoe_config_mutex);
+unsigned int fcoe_debug_logging;
+module_param_named(debug_logging, fcoe_debug_logging, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels");
+
+static DEFINE_MUTEX(fcoe_config_mutex);
static struct workqueue_struct *fcoe_wq;
@@ -67,8 +71,8 @@ static DECLARE_COMPLETION(fcoe_flush_completion);
/* fcoe host list */
/* must only by accessed under the RTNL mutex */
-LIST_HEAD(fcoe_hostlist);
-DEFINE_PER_CPU(struct fcoe_percpu_s, fcoe_percpu);
+static LIST_HEAD(fcoe_hostlist);
+static DEFINE_PER_CPU(struct fcoe_percpu_s, fcoe_percpu);
/* Function Prototypes */
static int fcoe_reset(struct Scsi_Host *);
@@ -157,7 +161,7 @@ static struct libfc_function_template fcoe_libfc_fcn_templ = {
.lport_set_port_id = fcoe_set_port_id,
};
-struct fc_function_template fcoe_nport_fc_functions = {
+static struct fc_function_template fcoe_nport_fc_functions = {
.show_host_node_name = 1,
.show_host_port_name = 1,
.show_host_supported_classes = 1,
@@ -197,7 +201,7 @@ struct fc_function_template fcoe_nport_fc_functions = {
.bsg_request = fc_lport_bsg_request,
};
-struct fc_function_template fcoe_vport_fc_functions = {
+static struct fc_function_template fcoe_vport_fc_functions = {
.show_host_node_name = 1,
.show_host_port_name = 1,
.show_host_supported_classes = 1,
@@ -433,7 +437,7 @@ static inline void fcoe_interface_put(struct fcoe_interface *fcoe)
*
* Caller must be holding the RTNL mutex
*/
-void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
+static void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
{
struct net_device *netdev = fcoe->netdev;
struct fcoe_ctlr *fip = &fcoe->ctlr;
@@ -748,7 +752,7 @@ static int fcoe_shost_config(struct fc_lport *lport, struct device *dev)
*
* Returns: True for read types I/O, otherwise returns false.
*/
-bool fcoe_oem_match(struct fc_frame *fp)
+static bool fcoe_oem_match(struct fc_frame *fp)
{
struct fc_frame_header *fh = fc_frame_header_get(fp);
struct fcp_cmnd *fcp;
@@ -756,11 +760,12 @@ bool fcoe_oem_match(struct fc_frame *fp)
if (fc_fcp_is_read(fr_fsp(fp)) &&
(fr_fsp(fp)->data_len > fcoe_ddp_min))
return true;
- else if (!(ntoh24(fh->fh_f_ctl) & FC_FC_EX_CTX)) {
+ else if ((fr_fsp(fp) == NULL) &&
+ (fh->fh_r_ctl == FC_RCTL_DD_UNSOL_CMD) &&
+ (ntohs(fh->fh_rx_id) == FC_XID_UNKNOWN)) {
fcp = fc_frame_payload_get(fp, sizeof(*fcp));
- if (ntohs(fh->fh_rx_id) == FC_XID_UNKNOWN &&
- fcp && (ntohl(fcp->fc_dl) > fcoe_ddp_min) &&
- (fcp->fc_flags & FCP_CFL_WRDATA))
+ if ((fcp->fc_flags & FCP_CFL_WRDATA) &&
+ (ntohl(fcp->fc_dl) > fcoe_ddp_min))
return true;
}
return false;
@@ -1106,7 +1111,7 @@ static int __init fcoe_if_init(void)
*
* Returns: 0 on success
*/
-int __exit fcoe_if_exit(void)
+static int __exit fcoe_if_exit(void)
{
fc_release_transport(fcoe_nport_scsi_transport);
fc_release_transport(fcoe_vport_scsi_transport);
@@ -1295,7 +1300,7 @@ static inline unsigned int fcoe_select_cpu(void)
*
* Returns: 0 for success
*/
-int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev,
+static int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev,
struct packet_type *ptype, struct net_device *olddev)
{
struct fc_lport *lport;
@@ -1451,7 +1456,7 @@ static int fcoe_alloc_paged_crc_eof(struct sk_buff *skb, int tlen)
*
* Return: 0 for success
*/
-int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp)
+static int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp)
{
int wlen;
u32 crc;
@@ -1671,8 +1676,7 @@ static void fcoe_recv_frame(struct sk_buff *skb)
skb->dev ? skb->dev->name : "<NULL>");
port = lport_priv(lport);
- if (skb_is_nonlinear(skb))
- skb_linearize(skb); /* not ideal */
+ skb_linearize(skb); /* check for skb_is_nonlinear is within skb_linearize */
/*
* Frame length checks and setting up the header pointers
@@ -1728,7 +1732,7 @@ drop:
*
* Return: 0 for success
*/
-int fcoe_percpu_receive_thread(void *arg)
+static int fcoe_percpu_receive_thread(void *arg)
{
struct fcoe_percpu_s *p = arg;
struct sk_buff *skb;
@@ -2146,7 +2150,7 @@ out_nortnl:
* Returns: 0 if the ethtool query was successful
* -1 if the ethtool query failed
*/
-int fcoe_link_speed_update(struct fc_lport *lport)
+static int fcoe_link_speed_update(struct fc_lport *lport)
{
struct net_device *netdev = fcoe_netdev(lport);
struct ethtool_cmd ecmd;
@@ -2180,7 +2184,7 @@ int fcoe_link_speed_update(struct fc_lport *lport)
* Returns: 0 if link is UP and OK, -1 if not
*
*/
-int fcoe_link_ok(struct fc_lport *lport)
+static int fcoe_link_ok(struct fc_lport *lport)
{
struct net_device *netdev = fcoe_netdev(lport);
@@ -2200,7 +2204,7 @@ int fcoe_link_ok(struct fc_lport *lport)
* there no packets that will be handled by the lport, but also that any
* threads already handling packet have returned.
*/
-void fcoe_percpu_clean(struct fc_lport *lport)
+static void fcoe_percpu_clean(struct fc_lport *lport)
{
struct fcoe_percpu_s *pp;
struct fcoe_rcv_info *fr;
@@ -2251,7 +2255,7 @@ void fcoe_percpu_clean(struct fc_lport *lport)
*
* Returns: Always 0 (return value required by FC transport template)
*/
-int fcoe_reset(struct Scsi_Host *shost)
+static int fcoe_reset(struct Scsi_Host *shost)
{
struct fc_lport *lport = shost_priv(shost);
struct fcoe_port *port = lport_priv(lport);
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h
index 6c6884bcf840..bcc89e639495 100644
--- a/drivers/scsi/fcoe/fcoe.h
+++ b/drivers/scsi/fcoe/fcoe.h
@@ -40,9 +40,7 @@
#define FCOE_MIN_XID 0x0000 /* the min xid supported by fcoe_sw */
#define FCOE_MAX_XID 0x0FFF /* the max xid supported by fcoe_sw */
-unsigned int fcoe_debug_logging;
-module_param_named(debug_logging, fcoe_debug_logging, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels");
+extern unsigned int fcoe_debug_logging;
#define FCOE_LOGGING 0x01 /* General logging, not categorized */
#define FCOE_NETDEV_LOGGING 0x02 /* Netdevice logging */
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 5140f5d0fd6b..b96962c39449 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -4271,7 +4271,9 @@ static void stop_controller_lockup_detector(struct ctlr_info *h)
remove_ctlr_from_lockup_detector_list(h);
/* If the list of ctlr's to monitor is empty, stop the thread */
if (list_empty(&hpsa_ctlr_list)) {
+ spin_unlock_irqrestore(&lockup_detector_lock, flags);
kthread_stop(hpsa_lockup_detector);
+ spin_lock_irqsave(&lockup_detector_lock, flags);
hpsa_lockup_detector = NULL;
}
spin_unlock_irqrestore(&lockup_detector_lock, flags);
diff --git a/drivers/scsi/isci/firmware/Makefile b/drivers/scsi/isci/firmware/Makefile
deleted file mode 100644
index 5f54461cabc5..000000000000
--- a/drivers/scsi/isci/firmware/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-# Makefile for create_fw
-#
-CC=gcc
-CFLAGS=-c -Wall -O2 -g
-LDFLAGS=
-SOURCES=create_fw.c
-OBJECTS=$(SOURCES:.cpp=.o)
-EXECUTABLE=create_fw
-
-all: $(SOURCES) $(EXECUTABLE)
-
-$(EXECUTABLE): $(OBJECTS)
- $(CC) $(LDFLAGS) $(OBJECTS) -o $@
-
-.c.o:
- $(CC) $(CFLAGS) $< -O $@
-
-clean:
- rm -f *.o $(EXECUTABLE)
diff --git a/drivers/scsi/isci/firmware/README b/drivers/scsi/isci/firmware/README
deleted file mode 100644
index 8056d2bd233b..000000000000
--- a/drivers/scsi/isci/firmware/README
+++ /dev/null
@@ -1,36 +0,0 @@
-This defines the temporary binary blow we are to pass to the SCU
-driver to emulate the binary firmware that we will eventually be
-able to access via NVRAM on the SCU controller.
-
-The current size of the binary blob is expected to be 149 bytes or larger
-
-Header Types:
-0x1: Phy Masks
-0x2: Phy Gens
-0x3: SAS Addrs
-0xff: End of Data
-
-ID string - u8[12]: "#SCU MAGIC#\0"
-Version - u8: 1
-SubVersion - u8: 0
-
-Header Type - u8: 0x1
-Size - u8: 8
-Phy Mask - u32[8]
-
-Header Type - u8: 0x2
-Size - u8: 8
-Phy Gen - u32[8]
-
-Header Type - u8: 0x3
-Size - u8: 8
-Sas Addr - u64[8]
-
-Header Type - u8: 0xf
-
-
-==============================================================================
-
-Place isci_firmware.bin in /lib/firmware
-Be sure to recreate the initramfs image to include the firmware.
-
diff --git a/drivers/scsi/isci/firmware/create_fw.c b/drivers/scsi/isci/firmware/create_fw.c
deleted file mode 100644
index c7a2887a7e95..000000000000
--- a/drivers/scsi/isci/firmware/create_fw.c
+++ /dev/null
@@ -1,99 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <string.h>
-#include <errno.h>
-#include <asm/types.h>
-#include <strings.h>
-#include <stdint.h>
-
-#include "create_fw.h"
-#include "../probe_roms.h"
-
-int write_blob(struct isci_orom *isci_orom)
-{
- FILE *fd;
- int err;
- size_t count;
-
- fd = fopen(blob_name, "w+");
- if (!fd) {
- perror("Open file for write failed");
- fclose(fd);
- return -EIO;
- }
-
- count = fwrite(isci_orom, sizeof(struct isci_orom), 1, fd);
- if (count != 1) {
- perror("Write data failed");
- fclose(fd);
- return -EIO;
- }
-
- fclose(fd);
-
- return 0;
-}
-
-void set_binary_values(struct isci_orom *isci_orom)
-{
- int ctrl_idx, phy_idx, port_idx;
-
- /* setting OROM signature */
- strncpy(isci_orom->hdr.signature, sig, strlen(sig));
- isci_orom->hdr.version = version;
- isci_orom->hdr.total_block_length = sizeof(struct isci_orom);
- isci_orom->hdr.hdr_length = sizeof(struct sci_bios_oem_param_block_hdr);
- isci_orom->hdr.num_elements = num_elements;
-
- for (ctrl_idx = 0; ctrl_idx < 2; ctrl_idx++) {
- isci_orom->ctrl[ctrl_idx].controller.mode_type = mode_type;
- isci_orom->ctrl[ctrl_idx].controller.max_concurrent_dev_spin_up =
- max_num_concurrent_dev_spin_up;
- isci_orom->ctrl[ctrl_idx].controller.do_enable_ssc =
- enable_ssc;
-
- for (port_idx = 0; port_idx < 4; port_idx++)
- isci_orom->ctrl[ctrl_idx].ports[port_idx].phy_mask =
- phy_mask[ctrl_idx][port_idx];
-
- for (phy_idx = 0; phy_idx < 4; phy_idx++) {
- isci_orom->ctrl[ctrl_idx].phys[phy_idx].sas_address.high =
- (__u32)(sas_addr[ctrl_idx][phy_idx] >> 32);
- isci_orom->ctrl[ctrl_idx].phys[phy_idx].sas_address.low =
- (__u32)(sas_addr[ctrl_idx][phy_idx]);
-
- isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control0 =
- afe_tx_amp_control0;
- isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control1 =
- afe_tx_amp_control1;
- isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control2 =
- afe_tx_amp_control2;
- isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control3 =
- afe_tx_amp_control3;
- }
- }
-}
-
-int main(void)
-{
- int err;
- struct isci_orom *isci_orom;
-
- isci_orom = malloc(sizeof(struct isci_orom));
- memset(isci_orom, 0, sizeof(struct isci_orom));
-
- set_binary_values(isci_orom);
-
- err = write_blob(isci_orom);
- if (err < 0) {
- free(isci_orom);
- return err;
- }
-
- free(isci_orom);
- return 0;
-}
diff --git a/drivers/scsi/isci/firmware/create_fw.h b/drivers/scsi/isci/firmware/create_fw.h
deleted file mode 100644
index 5f298828d22e..000000000000
--- a/drivers/scsi/isci/firmware/create_fw.h
+++ /dev/null
@@ -1,77 +0,0 @@
-#ifndef _CREATE_FW_H_
-#define _CREATE_FW_H_
-#include "../probe_roms.h"
-
-
-/* we are configuring for 2 SCUs */
-static const int num_elements = 2;
-
-/*
- * For all defined arrays:
- * elements 0-3 are for SCU0, ports 0-3
- * elements 4-7 are for SCU1, ports 0-3
- *
- * valid configurations for one SCU are:
- * P0 P1 P2 P3
- * ----------------
- * 0xF,0x0,0x0,0x0 # 1 x4 port
- * 0x3,0x0,0x4,0x8 # Phys 0 and 1 are a x2 port, phy 2 and phy 3 are each x1
- * # ports
- * 0x1,0x2,0xC,0x0 # Phys 0 and 1 are each x1 ports, phy 2 and phy 3 are a x2
- * # port
- * 0x3,0x0,0xC,0x0 # Phys 0 and 1 are a x2 port, phy 2 and phy 3 are a x2 port
- * 0x1,0x2,0x4,0x8 # Each phy is a x1 port (this is the default configuration)
- *
- * if there is a port/phy on which you do not wish to override the default
- * values, use the value assigned to UNINIT_PARAM (255).
- */
-
-/* discovery mode type (port auto config mode by default ) */
-
-/*
- * if there is a port/phy on which you do not wish to override the default
- * values, use the value "0000000000000000". SAS address of zero's is
- * considered invalid and will not be used.
- */
-#ifdef MPC
-static const int mode_type = SCIC_PORT_MANUAL_CONFIGURATION_MODE;
-static const __u8 phy_mask[2][4] = { {1, 2, 4, 8},
- {1, 2, 4, 8} };
-static const unsigned long long sas_addr[2][4] = { { 0x5FCFFFFFF0000001ULL,
- 0x5FCFFFFFF0000002ULL,
- 0x5FCFFFFFF0000003ULL,
- 0x5FCFFFFFF0000004ULL },
- { 0x5FCFFFFFF0000005ULL,
- 0x5FCFFFFFF0000006ULL,
- 0x5FCFFFFFF0000007ULL,
- 0x5FCFFFFFF0000008ULL } };
-#else /* APC (default) */
-static const int mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE;
-static const __u8 phy_mask[2][4];
-static const unsigned long long sas_addr[2][4] = { { 0x5FCFFFFF00000001ULL,
- 0x5FCFFFFF00000001ULL,
- 0x5FCFFFFF00000001ULL,
- 0x5FCFFFFF00000001ULL },
- { 0x5FCFFFFF00000002ULL,
- 0x5FCFFFFF00000002ULL,
- 0x5FCFFFFF00000002ULL,
- 0x5FCFFFFF00000002ULL } };
-#endif
-
-/* Maximum number of concurrent device spin up */
-static const int max_num_concurrent_dev_spin_up = 1;
-
-/* enable of ssc operation */
-static const int enable_ssc;
-
-/* AFE_TX_AMP_CONTROL */
-static const unsigned int afe_tx_amp_control0 = 0x000bdd08;
-static const unsigned int afe_tx_amp_control1 = 0x000ffc00;
-static const unsigned int afe_tx_amp_control2 = 0x000b7c09;
-static const unsigned int afe_tx_amp_control3 = 0x000afc6e;
-
-static const char blob_name[] = "isci_firmware.bin";
-static const char sig[] = "ISCUOEMB";
-static const unsigned char version = 0x10;
-
-#endif
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c
index e7fe9c4c85b8..1a65d6514237 100644
--- a/drivers/scsi/isci/host.c
+++ b/drivers/scsi/isci/host.c
@@ -899,7 +899,8 @@ static enum sci_status sci_controller_start_next_phy(struct isci_host *ihost)
*/
if ((iphy->is_in_link_training == false && state == SCI_PHY_INITIAL) ||
(iphy->is_in_link_training == false && state == SCI_PHY_STOPPED) ||
- (iphy->is_in_link_training == true && is_phy_starting(iphy))) {
+ (iphy->is_in_link_training == true && is_phy_starting(iphy)) ||
+ (ihost->port_agent.phy_ready_mask != ihost->port_agent.phy_configured_mask)) {
is_controller_start_complete = false;
break;
}
@@ -1666,6 +1667,9 @@ static void sci_controller_set_default_config_parameters(struct isci_host *ihost
/* Default to no SSC operation. */
ihost->oem_parameters.controller.do_enable_ssc = false;
+ /* Default to short cables on all phys. */
+ ihost->oem_parameters.controller.cable_selection_mask = 0;
+
/* Initialize all of the port parameter information to narrow ports. */
for (index = 0; index < SCI_MAX_PORTS; index++) {
ihost->oem_parameters.ports[index].phy_mask = 0;
@@ -1673,8 +1677,9 @@ static void sci_controller_set_default_config_parameters(struct isci_host *ihost
/* Initialize all of the phy parameter information. */
for (index = 0; index < SCI_MAX_PHYS; index++) {
- /* Default to 6G (i.e. Gen 3) for now. */
- ihost->user_parameters.phys[index].max_speed_generation = 3;
+ /* Default to 3G (i.e. Gen 2). */
+ ihost->user_parameters.phys[index].max_speed_generation =
+ SCIC_SDS_PARM_GEN2_SPEED;
/* the frequencies cannot be 0 */
ihost->user_parameters.phys[index].align_insertion_frequency = 0x7f;
@@ -1694,7 +1699,7 @@ static void sci_controller_set_default_config_parameters(struct isci_host *ihost
ihost->user_parameters.ssp_inactivity_timeout = 5;
ihost->user_parameters.stp_max_occupancy_timeout = 5;
ihost->user_parameters.ssp_max_occupancy_timeout = 20;
- ihost->user_parameters.no_outbound_task_timeout = 20;
+ ihost->user_parameters.no_outbound_task_timeout = 2;
}
static void controller_timeout(unsigned long data)
@@ -1759,7 +1764,7 @@ static enum sci_status sci_controller_construct(struct isci_host *ihost,
return sci_controller_reset(ihost);
}
-int sci_oem_parameters_validate(struct sci_oem_params *oem)
+int sci_oem_parameters_validate(struct sci_oem_params *oem, u8 version)
{
int i;
@@ -1791,18 +1796,61 @@ int sci_oem_parameters_validate(struct sci_oem_params *oem)
oem->controller.max_concurr_spin_up < 1)
return -EINVAL;
+ if (oem->controller.do_enable_ssc) {
+ if (version < ISCI_ROM_VER_1_1 && oem->controller.do_enable_ssc != 1)
+ return -EINVAL;
+
+ if (version >= ISCI_ROM_VER_1_1) {
+ u8 test = oem->controller.ssc_sata_tx_spread_level;
+
+ switch (test) {
+ case 0:
+ case 2:
+ case 3:
+ case 6:
+ case 7:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ test = oem->controller.ssc_sas_tx_spread_level;
+ if (oem->controller.ssc_sas_tx_type == 0) {
+ switch (test) {
+ case 0:
+ case 2:
+ case 3:
+ break;
+ default:
+ return -EINVAL;
+ }
+ } else if (oem->controller.ssc_sas_tx_type == 1) {
+ switch (test) {
+ case 0:
+ case 3:
+ case 6:
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+ }
+ }
+
return 0;
}
static enum sci_status sci_oem_parameters_set(struct isci_host *ihost)
{
u32 state = ihost->sm.current_state_id;
+ struct isci_pci_info *pci_info = to_pci_info(ihost->pdev);
if (state == SCIC_RESET ||
state == SCIC_INITIALIZING ||
state == SCIC_INITIALIZED) {
- if (sci_oem_parameters_validate(&ihost->oem_parameters))
+ if (sci_oem_parameters_validate(&ihost->oem_parameters,
+ pci_info->orom->hdr.version))
return SCI_FAILURE_INVALID_PARAMETER_VALUE;
return SCI_SUCCESS;
@@ -1857,6 +1905,31 @@ static void power_control_timeout(unsigned long data)
ihost->power_control.phys_waiting--;
ihost->power_control.phys_granted_power++;
sci_phy_consume_power_handler(iphy);
+
+ if (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) {
+ u8 j;
+
+ for (j = 0; j < SCI_MAX_PHYS; j++) {
+ struct isci_phy *requester = ihost->power_control.requesters[j];
+
+ /*
+ * Search the power_control queue to see if there are other phys
+ * attached to the same remote device. If found, take all of
+ * them out of await_sas_power state.
+ */
+ if (requester != NULL && requester != iphy) {
+ u8 other = memcmp(requester->frame_rcvd.iaf.sas_addr,
+ iphy->frame_rcvd.iaf.sas_addr,
+ sizeof(requester->frame_rcvd.iaf.sas_addr));
+
+ if (other == 0) {
+ ihost->power_control.requesters[j] = NULL;
+ ihost->power_control.phys_waiting--;
+ sci_phy_consume_power_handler(requester);
+ }
+ }
+ }
+ }
}
/*
@@ -1891,9 +1964,34 @@ void sci_controller_power_control_queue_insert(struct isci_host *ihost,
ihost->power_control.timer_started = true;
} else {
- /* Add the phy in the waiting list */
- ihost->power_control.requesters[iphy->phy_index] = iphy;
- ihost->power_control.phys_waiting++;
+ /*
+ * There are phys, attached to the same sas address as this phy, are
+ * already in READY state, this phy don't need wait.
+ */
+ u8 i;
+ struct isci_phy *current_phy;
+
+ for (i = 0; i < SCI_MAX_PHYS; i++) {
+ u8 other;
+ current_phy = &ihost->phys[i];
+
+ other = memcmp(current_phy->frame_rcvd.iaf.sas_addr,
+ iphy->frame_rcvd.iaf.sas_addr,
+ sizeof(current_phy->frame_rcvd.iaf.sas_addr));
+
+ if (current_phy->sm.current_state_id == SCI_PHY_READY &&
+ current_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS &&
+ other == 0) {
+ sci_phy_consume_power_handler(iphy);
+ break;
+ }
+ }
+
+ if (i == SCI_MAX_PHYS) {
+ /* Add the phy in the waiting list */
+ ihost->power_control.requesters[iphy->phy_index] = iphy;
+ ihost->power_control.phys_waiting++;
+ }
}
}
@@ -1908,162 +2006,250 @@ void sci_controller_power_control_queue_remove(struct isci_host *ihost,
ihost->power_control.requesters[iphy->phy_index] = NULL;
}
+static int is_long_cable(int phy, unsigned char selection_byte)
+{
+ return !!(selection_byte & (1 << phy));
+}
+
+static int is_medium_cable(int phy, unsigned char selection_byte)
+{
+ return !!(selection_byte & (1 << (phy + 4)));
+}
+
+static enum cable_selections decode_selection_byte(
+ int phy,
+ unsigned char selection_byte)
+{
+ return ((selection_byte & (1 << phy)) ? 1 : 0)
+ + (selection_byte & (1 << (phy + 4)) ? 2 : 0);
+}
+
+static unsigned char *to_cable_select(struct isci_host *ihost)
+{
+ if (is_cable_select_overridden())
+ return ((unsigned char *)&cable_selection_override)
+ + ihost->id;
+ else
+ return &ihost->oem_parameters.controller.cable_selection_mask;
+}
+
+enum cable_selections decode_cable_selection(struct isci_host *ihost, int phy)
+{
+ return decode_selection_byte(phy, *to_cable_select(ihost));
+}
+
+char *lookup_cable_names(enum cable_selections selection)
+{
+ static char *cable_names[] = {
+ [short_cable] = "short",
+ [long_cable] = "long",
+ [medium_cable] = "medium",
+ [undefined_cable] = "<undefined, assumed long>" /* bit 0==1 */
+ };
+ return (selection <= undefined_cable) ? cable_names[selection]
+ : cable_names[undefined_cable];
+}
+
#define AFE_REGISTER_WRITE_DELAY 10
-/* Initialize the AFE for this phy index. We need to read the AFE setup from
- * the OEM parameters
- */
static void sci_controller_afe_initialization(struct isci_host *ihost)
{
+ struct scu_afe_registers __iomem *afe = &ihost->scu_registers->afe;
const struct sci_oem_params *oem = &ihost->oem_parameters;
struct pci_dev *pdev = ihost->pdev;
u32 afe_status;
u32 phy_id;
+ unsigned char cable_selection_mask = *to_cable_select(ihost);
/* Clear DFX Status registers */
- writel(0x0081000f, &ihost->scu_registers->afe.afe_dfx_master_control0);
+ writel(0x0081000f, &afe->afe_dfx_master_control0);
udelay(AFE_REGISTER_WRITE_DELAY);
- if (is_b0(pdev)) {
+ if (is_b0(pdev) || is_c0(pdev) || is_c1(pdev)) {
/* PM Rx Equalization Save, PM SPhy Rx Acknowledgement
- * Timer, PM Stagger Timer */
- writel(0x0007BFFF, &ihost->scu_registers->afe.afe_pmsn_master_control2);
+ * Timer, PM Stagger Timer
+ */
+ writel(0x0007FFFF, &afe->afe_pmsn_master_control2);
udelay(AFE_REGISTER_WRITE_DELAY);
}
/* Configure bias currents to normal */
if (is_a2(pdev))
- writel(0x00005A00, &ihost->scu_registers->afe.afe_bias_control);
+ writel(0x00005A00, &afe->afe_bias_control);
else if (is_b0(pdev) || is_c0(pdev))
- writel(0x00005F00, &ihost->scu_registers->afe.afe_bias_control);
+ writel(0x00005F00, &afe->afe_bias_control);
+ else if (is_c1(pdev))
+ writel(0x00005500, &afe->afe_bias_control);
udelay(AFE_REGISTER_WRITE_DELAY);
/* Enable PLL */
- if (is_b0(pdev) || is_c0(pdev))
- writel(0x80040A08, &ihost->scu_registers->afe.afe_pll_control0);
- else
- writel(0x80040908, &ihost->scu_registers->afe.afe_pll_control0);
+ if (is_a2(pdev))
+ writel(0x80040908, &afe->afe_pll_control0);
+ else if (is_b0(pdev) || is_c0(pdev))
+ writel(0x80040A08, &afe->afe_pll_control0);
+ else if (is_c1(pdev)) {
+ writel(0x80000B08, &afe->afe_pll_control0);
+ udelay(AFE_REGISTER_WRITE_DELAY);
+ writel(0x00000B08, &afe->afe_pll_control0);
+ udelay(AFE_REGISTER_WRITE_DELAY);
+ writel(0x80000B08, &afe->afe_pll_control0);
+ }
udelay(AFE_REGISTER_WRITE_DELAY);
/* Wait for the PLL to lock */
do {
- afe_status = readl(&ihost->scu_registers->afe.afe_common_block_status);
+ afe_status = readl(&afe->afe_common_block_status);
udelay(AFE_REGISTER_WRITE_DELAY);
} while ((afe_status & 0x00001000) == 0);
if (is_a2(pdev)) {
- /* Shorten SAS SNW lock time (RxLock timer value from 76 us to 50 us) */
- writel(0x7bcc96ad, &ihost->scu_registers->afe.afe_pmsn_master_control0);
+ /* Shorten SAS SNW lock time (RxLock timer value from 76
+ * us to 50 us)
+ */
+ writel(0x7bcc96ad, &afe->afe_pmsn_master_control0);
udelay(AFE_REGISTER_WRITE_DELAY);
}
for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++) {
+ struct scu_afe_transceiver *xcvr = &afe->scu_afe_xcvr[phy_id];
const struct sci_phy_oem_params *oem_phy = &oem->phys[phy_id];
+ int cable_length_long =
+ is_long_cable(phy_id, cable_selection_mask);
+ int cable_length_medium =
+ is_medium_cable(phy_id, cable_selection_mask);
- if (is_b0(pdev)) {
- /* Configure transmitter SSC parameters */
- writel(0x00030000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_ssc_control);
+ if (is_a2(pdev)) {
+ /* All defaults, except the Receive Word
+ * Alignament/Comma Detect Enable....(0xe800)
+ */
+ writel(0x00004512, &xcvr->afe_xcvr_control0);
+ udelay(AFE_REGISTER_WRITE_DELAY);
+
+ writel(0x0050100F, &xcvr->afe_xcvr_control1);
+ udelay(AFE_REGISTER_WRITE_DELAY);
+ } else if (is_b0(pdev)) {
+ /* Configure transmitter SSC parameters */
+ writel(0x00030000, &xcvr->afe_tx_ssc_control);
udelay(AFE_REGISTER_WRITE_DELAY);
} else if (is_c0(pdev)) {
- /* Configure transmitter SSC parameters */
- writel(0x0003000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_ssc_control);
+ /* Configure transmitter SSC parameters */
+ writel(0x00010202, &xcvr->afe_tx_ssc_control);
udelay(AFE_REGISTER_WRITE_DELAY);
- /*
- * All defaults, except the Receive Word Alignament/Comma Detect
- * Enable....(0xe800) */
- writel(0x00004500, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control0);
+ /* All defaults, except the Receive Word
+ * Alignament/Comma Detect Enable....(0xe800)
+ */
+ writel(0x00014500, &xcvr->afe_xcvr_control0);
udelay(AFE_REGISTER_WRITE_DELAY);
- } else {
- /*
- * All defaults, except the Receive Word Alignament/Comma Detect
- * Enable....(0xe800) */
- writel(0x00004512, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control0);
+ } else if (is_c1(pdev)) {
+ /* Configure transmitter SSC parameters */
+ writel(0x00010202, &xcvr->afe_tx_ssc_control);
udelay(AFE_REGISTER_WRITE_DELAY);
- writel(0x0050100F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control1);
+ /* All defaults, except the Receive Word
+ * Alignament/Comma Detect Enable....(0xe800)
+ */
+ writel(0x0001C500, &xcvr->afe_xcvr_control0);
udelay(AFE_REGISTER_WRITE_DELAY);
}
- /*
- * Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
- * & increase TX int & ext bias 20%....(0xe85c) */
+ /* Power up TX and RX out from power down (PWRDNTX and
+ * PWRDNRX) & increase TX int & ext bias 20%....(0xe85c)
+ */
if (is_a2(pdev))
- writel(0x000003F0, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);
+ writel(0x000003F0, &xcvr->afe_channel_control);
else if (is_b0(pdev)) {
- /* Power down TX and RX (PWRDNTX and PWRDNRX) */
- writel(0x000003D7, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);
+ writel(0x000003D7, &xcvr->afe_channel_control);
udelay(AFE_REGISTER_WRITE_DELAY);
- /*
- * Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
- * & increase TX int & ext bias 20%....(0xe85c) */
- writel(0x000003D4, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);
- } else {
- writel(0x000001E7, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);
+ writel(0x000003D4, &xcvr->afe_channel_control);
+ } else if (is_c0(pdev)) {
+ writel(0x000001E7, &xcvr->afe_channel_control);
udelay(AFE_REGISTER_WRITE_DELAY);
- /*
- * Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
- * & increase TX int & ext bias 20%....(0xe85c) */
- writel(0x000001E4, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);
+ writel(0x000001E4, &xcvr->afe_channel_control);
+ } else if (is_c1(pdev)) {
+ writel(cable_length_long ? 0x000002F7 : 0x000001F7,
+ &xcvr->afe_channel_control);
+ udelay(AFE_REGISTER_WRITE_DELAY);
+
+ writel(cable_length_long ? 0x000002F4 : 0x000001F4,
+ &xcvr->afe_channel_control);
}
udelay(AFE_REGISTER_WRITE_DELAY);
if (is_a2(pdev)) {
/* Enable TX equalization (0xe824) */
- writel(0x00040000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control);
+ writel(0x00040000, &xcvr->afe_tx_control);
udelay(AFE_REGISTER_WRITE_DELAY);
}
- /*
- * RDPI=0x0(RX Power On), RXOOBDETPDNC=0x0, TPD=0x0(TX Power On),
- * RDD=0x0(RX Detect Enabled) ....(0xe800) */
- writel(0x00004100, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control0);
+ if (is_a2(pdev) || is_b0(pdev))
+ /* RDPI=0x0(RX Power On), RXOOBDETPDNC=0x0,
+ * TPD=0x0(TX Power On), RDD=0x0(RX Detect
+ * Enabled) ....(0xe800)
+ */
+ writel(0x00004100, &xcvr->afe_xcvr_control0);
+ else if (is_c0(pdev))
+ writel(0x00014100, &xcvr->afe_xcvr_control0);
+ else if (is_c1(pdev))
+ writel(0x0001C100, &xcvr->afe_xcvr_control0);
udelay(AFE_REGISTER_WRITE_DELAY);
/* Leave DFE/FFE on */
if (is_a2(pdev))
- writel(0x3F11103F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0);
+ writel(0x3F11103F, &xcvr->afe_rx_ssc_control0);
else if (is_b0(pdev)) {
- writel(0x3F11103F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0);
+ writel(0x3F11103F, &xcvr->afe_rx_ssc_control0);
udelay(AFE_REGISTER_WRITE_DELAY);
/* Enable TX equalization (0xe824) */
- writel(0x00040000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control);
- } else {
- writel(0x0140DF0F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control1);
+ writel(0x00040000, &xcvr->afe_tx_control);
+ } else if (is_c0(pdev)) {
+ writel(0x01400C0F, &xcvr->afe_rx_ssc_control1);
+ udelay(AFE_REGISTER_WRITE_DELAY);
+
+ writel(0x3F6F103F, &xcvr->afe_rx_ssc_control0);
+ udelay(AFE_REGISTER_WRITE_DELAY);
+
+ /* Enable TX equalization (0xe824) */
+ writel(0x00040000, &xcvr->afe_tx_control);
+ } else if (is_c1(pdev)) {
+ writel(cable_length_long ? 0x01500C0C :
+ cable_length_medium ? 0x01400C0D : 0x02400C0D,
+ &xcvr->afe_xcvr_control1);
+ udelay(AFE_REGISTER_WRITE_DELAY);
+
+ writel(0x000003E0, &xcvr->afe_dfx_rx_control1);
udelay(AFE_REGISTER_WRITE_DELAY);
- writel(0x3F6F103F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0);
+ writel(cable_length_long ? 0x33091C1F :
+ cable_length_medium ? 0x3315181F : 0x2B17161F,
+ &xcvr->afe_rx_ssc_control0);
udelay(AFE_REGISTER_WRITE_DELAY);
/* Enable TX equalization (0xe824) */
- writel(0x00040000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control);
+ writel(0x00040000, &xcvr->afe_tx_control);
}
udelay(AFE_REGISTER_WRITE_DELAY);
- writel(oem_phy->afe_tx_amp_control0,
- &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control0);
+ writel(oem_phy->afe_tx_amp_control0, &xcvr->afe_tx_amp_control0);
udelay(AFE_REGISTER_WRITE_DELAY);
- writel(oem_phy->afe_tx_amp_control1,
- &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control1);
+ writel(oem_phy->afe_tx_amp_control1, &xcvr->afe_tx_amp_control1);
udelay(AFE_REGISTER_WRITE_DELAY);
- writel(oem_phy->afe_tx_amp_control2,
- &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control2);
+ writel(oem_phy->afe_tx_amp_control2, &xcvr->afe_tx_amp_control2);
udelay(AFE_REGISTER_WRITE_DELAY);
- writel(oem_phy->afe_tx_amp_control3,
- &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control3);
+ writel(oem_phy->afe_tx_amp_control3, &xcvr->afe_tx_amp_control3);
udelay(AFE_REGISTER_WRITE_DELAY);
}
/* Transfer control to the PEs */
- writel(0x00010f00, &ihost->scu_registers->afe.afe_dfx_master_control0);
+ writel(0x00010f00, &afe->afe_dfx_master_control0);
udelay(AFE_REGISTER_WRITE_DELAY);
}
diff --git a/drivers/scsi/isci/host.h b/drivers/scsi/isci/host.h
index 646051afd3cb..5477f0fa8233 100644
--- a/drivers/scsi/isci/host.h
+++ b/drivers/scsi/isci/host.h
@@ -435,11 +435,36 @@ static inline bool is_b0(struct pci_dev *pdev)
static inline bool is_c0(struct pci_dev *pdev)
{
- if (pdev->revision >= 5)
+ if (pdev->revision == 5)
return true;
return false;
}
+static inline bool is_c1(struct pci_dev *pdev)
+{
+ if (pdev->revision >= 6)
+ return true;
+ return false;
+}
+
+enum cable_selections {
+ short_cable = 0,
+ long_cable = 1,
+ medium_cable = 2,
+ undefined_cable = 3
+};
+
+#define CABLE_OVERRIDE_DISABLED (0x10000)
+
+static inline int is_cable_select_overridden(void)
+{
+ return cable_selection_override < CABLE_OVERRIDE_DISABLED;
+}
+
+enum cable_selections decode_cable_selection(struct isci_host *ihost, int phy);
+void validate_cable_selections(struct isci_host *ihost);
+char *lookup_cable_names(enum cable_selections);
+
/* set hw control for 'activity', even though active enclosures seem to drive
* the activity led on their own. Skip setting FSENG control on 'status' due
* to unexpected operation and 'error' due to not being a supported automatic
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index a97edabcb85a..17c4c2c89c2e 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -65,7 +65,7 @@
#include "probe_roms.h"
#define MAJ 1
-#define MIN 0
+#define MIN 1
#define BUILD 0
#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
__stringify(BUILD)
@@ -94,7 +94,7 @@ MODULE_DEVICE_TABLE(pci, isci_id_table);
/* linux isci specific settings */
-unsigned char no_outbound_task_to = 20;
+unsigned char no_outbound_task_to = 2;
module_param(no_outbound_task_to, byte, 0);
MODULE_PARM_DESC(no_outbound_task_to, "No Outbound Task Timeout (1us incr)");
@@ -114,7 +114,7 @@ u16 stp_inactive_to = 5;
module_param(stp_inactive_to, ushort, 0);
MODULE_PARM_DESC(stp_inactive_to, "STP inactivity timeout (100us incr)");
-unsigned char phy_gen = 3;
+unsigned char phy_gen = SCIC_SDS_PARM_GEN2_SPEED;
module_param(phy_gen, byte, 0);
MODULE_PARM_DESC(phy_gen, "PHY generation (1: 1.5Gbps 2: 3.0Gbps 3: 6.0Gbps)");
@@ -122,6 +122,14 @@ unsigned char max_concurr_spinup;
module_param(max_concurr_spinup, byte, 0);
MODULE_PARM_DESC(max_concurr_spinup, "Max concurrent device spinup");
+uint cable_selection_override = CABLE_OVERRIDE_DISABLED;
+module_param(cable_selection_override, uint, 0);
+
+MODULE_PARM_DESC(cable_selection_override,
+ "This field indicates length of the SAS/SATA cable between "
+ "host and device. If any bits > 15 are set (default) "
+ "indicates \"use platform defaults\"");
+
static ssize_t isci_show_id(struct device *dev, struct device_attribute *attr, char *buf)
{
struct Scsi_Host *shost = container_of(dev, typeof(*shost), shost_dev);
@@ -412,6 +420,14 @@ static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id)
return NULL;
isci_host->shost = shost;
+ dev_info(&pdev->dev, "%sSCU controller %d: phy 3-0 cables: "
+ "{%s, %s, %s, %s}\n",
+ (is_cable_select_overridden() ? "* " : ""), isci_host->id,
+ lookup_cable_names(decode_cable_selection(isci_host, 3)),
+ lookup_cable_names(decode_cable_selection(isci_host, 2)),
+ lookup_cable_names(decode_cable_selection(isci_host, 1)),
+ lookup_cable_names(decode_cable_selection(isci_host, 0)));
+
err = isci_host_init(isci_host);
if (err)
goto err_shost;
@@ -466,7 +482,8 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic
orom = isci_request_oprom(pdev);
for (i = 0; orom && i < ARRAY_SIZE(orom->ctrl); i++) {
- if (sci_oem_parameters_validate(&orom->ctrl[i])) {
+ if (sci_oem_parameters_validate(&orom->ctrl[i],
+ orom->hdr.version)) {
dev_warn(&pdev->dev,
"[%d]: invalid oem parameters detected, falling back to firmware\n", i);
devm_kfree(&pdev->dev, orom);
diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h
index 8efeb6b08321..234ab46fce33 100644
--- a/drivers/scsi/isci/isci.h
+++ b/drivers/scsi/isci/isci.h
@@ -480,6 +480,7 @@ extern u16 ssp_inactive_to;
extern u16 stp_inactive_to;
extern unsigned char phy_gen;
extern unsigned char max_concurr_spinup;
+extern uint cable_selection_override;
irqreturn_t isci_msix_isr(int vec, void *data);
irqreturn_t isci_intx_isr(int vec, void *data);
diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c
index 35f50c2183e1..fe18acfd6eb3 100644
--- a/drivers/scsi/isci/phy.c
+++ b/drivers/scsi/isci/phy.c
@@ -91,22 +91,23 @@ sci_phy_transport_layer_initialization(struct isci_phy *iphy,
static enum sci_status
sci_phy_link_layer_initialization(struct isci_phy *iphy,
- struct scu_link_layer_registers __iomem *reg)
+ struct scu_link_layer_registers __iomem *llr)
{
struct isci_host *ihost = iphy->owning_port->owning_controller;
+ struct sci_phy_user_params *phy_user;
+ struct sci_phy_oem_params *phy_oem;
int phy_idx = iphy->phy_index;
- struct sci_phy_user_params *phy_user = &ihost->user_parameters.phys[phy_idx];
- struct sci_phy_oem_params *phy_oem =
- &ihost->oem_parameters.phys[phy_idx];
- u32 phy_configuration;
struct sci_phy_cap phy_cap;
+ u32 phy_configuration;
u32 parity_check = 0;
u32 parity_count = 0;
u32 llctl, link_rate;
u32 clksm_value = 0;
u32 sp_timeouts = 0;
- iphy->link_layer_registers = reg;
+ phy_user = &ihost->user_parameters.phys[phy_idx];
+ phy_oem = &ihost->oem_parameters.phys[phy_idx];
+ iphy->link_layer_registers = llr;
/* Set our IDENTIFY frame data */
#define SCI_END_DEVICE 0x01
@@ -116,32 +117,26 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy,
SCU_SAS_TIID_GEN_BIT(STP_INITIATOR) |
SCU_SAS_TIID_GEN_BIT(DA_SATA_HOST) |
SCU_SAS_TIID_GEN_VAL(DEVICE_TYPE, SCI_END_DEVICE),
- &iphy->link_layer_registers->transmit_identification);
+ &llr->transmit_identification);
/* Write the device SAS Address */
- writel(0xFEDCBA98,
- &iphy->link_layer_registers->sas_device_name_high);
- writel(phy_idx, &iphy->link_layer_registers->sas_device_name_low);
+ writel(0xFEDCBA98, &llr->sas_device_name_high);
+ writel(phy_idx, &llr->sas_device_name_low);
/* Write the source SAS Address */
- writel(phy_oem->sas_address.high,
- &iphy->link_layer_registers->source_sas_address_high);
- writel(phy_oem->sas_address.low,
- &iphy->link_layer_registers->source_sas_address_low);
+ writel(phy_oem->sas_address.high, &llr->source_sas_address_high);
+ writel(phy_oem->sas_address.low, &llr->source_sas_address_low);
/* Clear and Set the PHY Identifier */
- writel(0, &iphy->link_layer_registers->identify_frame_phy_id);
- writel(SCU_SAS_TIPID_GEN_VALUE(ID, phy_idx),
- &iphy->link_layer_registers->identify_frame_phy_id);
+ writel(0, &llr->identify_frame_phy_id);
+ writel(SCU_SAS_TIPID_GEN_VALUE(ID, phy_idx), &llr->identify_frame_phy_id);
/* Change the initial state of the phy configuration register */
- phy_configuration =
- readl(&iphy->link_layer_registers->phy_configuration);
+ phy_configuration = readl(&llr->phy_configuration);
/* Hold OOB state machine in reset */
phy_configuration |= SCU_SAS_PCFG_GEN_BIT(OOB_RESET);
- writel(phy_configuration,
- &iphy->link_layer_registers->phy_configuration);
+ writel(phy_configuration, &llr->phy_configuration);
/* Configure the SNW capabilities */
phy_cap.all = 0;
@@ -149,15 +144,64 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy,
phy_cap.gen3_no_ssc = 1;
phy_cap.gen2_no_ssc = 1;
phy_cap.gen1_no_ssc = 1;
- if (ihost->oem_parameters.controller.do_enable_ssc == true) {
+ if (ihost->oem_parameters.controller.do_enable_ssc) {
+ struct scu_afe_registers __iomem *afe = &ihost->scu_registers->afe;
+ struct scu_afe_transceiver *xcvr = &afe->scu_afe_xcvr[phy_idx];
+ struct isci_pci_info *pci_info = to_pci_info(ihost->pdev);
+ bool en_sas = false;
+ bool en_sata = false;
+ u32 sas_type = 0;
+ u32 sata_spread = 0x2;
+ u32 sas_spread = 0x2;
+
phy_cap.gen3_ssc = 1;
phy_cap.gen2_ssc = 1;
phy_cap.gen1_ssc = 1;
+
+ if (pci_info->orom->hdr.version < ISCI_ROM_VER_1_1)
+ en_sas = en_sata = true;
+ else {
+ sata_spread = ihost->oem_parameters.controller.ssc_sata_tx_spread_level;
+ sas_spread = ihost->oem_parameters.controller.ssc_sas_tx_spread_level;
+
+ if (sata_spread)
+ en_sata = true;
+
+ if (sas_spread) {
+ en_sas = true;
+ sas_type = ihost->oem_parameters.controller.ssc_sas_tx_type;
+ }
+
+ }
+
+ if (en_sas) {
+ u32 reg;
+
+ reg = readl(&xcvr->afe_xcvr_control0);
+ reg |= (0x00100000 | (sas_type << 19));
+ writel(reg, &xcvr->afe_xcvr_control0);
+
+ reg = readl(&xcvr->afe_tx_ssc_control);
+ reg |= sas_spread << 8;
+ writel(reg, &xcvr->afe_tx_ssc_control);
+ }
+
+ if (en_sata) {
+ u32 reg;
+
+ reg = readl(&xcvr->afe_tx_ssc_control);
+ reg |= sata_spread;
+ writel(reg, &xcvr->afe_tx_ssc_control);
+
+ reg = readl(&llr->stp_control);
+ reg |= 1 << 12;
+ writel(reg, &llr->stp_control);
+ }
}
- /*
- * The SAS specification indicates that the phy_capabilities that
- * are transmitted shall have an even parity. Calculate the parity. */
+ /* The SAS specification indicates that the phy_capabilities that
+ * are transmitted shall have an even parity. Calculate the parity.
+ */
parity_check = phy_cap.all;
while (parity_check != 0) {
if (parity_check & 0x1)
@@ -165,20 +209,20 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy,
parity_check >>= 1;
}
- /*
- * If parity indicates there are an odd number of bits set, then
- * set the parity bit to 1 in the phy capabilities. */
+ /* If parity indicates there are an odd number of bits set, then
+ * set the parity bit to 1 in the phy capabilities.
+ */
if ((parity_count % 2) != 0)
phy_cap.parity = 1;
- writel(phy_cap.all, &iphy->link_layer_registers->phy_capabilities);
+ writel(phy_cap.all, &llr->phy_capabilities);
/* Set the enable spinup period but disable the ability to send
* notify enable spinup
*/
writel(SCU_ENSPINUP_GEN_VAL(COUNT,
phy_user->notify_enable_spin_up_insertion_frequency),
- &iphy->link_layer_registers->notify_enable_spinup_control);
+ &llr->notify_enable_spinup_control);
/* Write the ALIGN Insertion Ferequency for connected phy and
* inpendent of connected state
@@ -189,11 +233,13 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy,
clksm_value |= SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL(GENERAL,
phy_user->align_insertion_frequency);
- writel(clksm_value, &iphy->link_layer_registers->clock_skew_management);
+ writel(clksm_value, &llr->clock_skew_management);
- /* @todo Provide a way to write this register correctly */
- writel(0x02108421,
- &iphy->link_layer_registers->afe_lookup_table_control);
+ if (is_c0(ihost->pdev) || is_c1(ihost->pdev)) {
+ writel(0x04210400, &llr->afe_lookup_table_control);
+ writel(0x020A7C05, &llr->sas_primitive_timeout);
+ } else
+ writel(0x02108421, &llr->afe_lookup_table_control);
llctl = SCU_SAS_LLCTL_GEN_VAL(NO_OUTBOUND_TASK_TIMEOUT,
(u8)ihost->user_parameters.no_outbound_task_timeout);
@@ -210,9 +256,9 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy,
break;
}
llctl |= SCU_SAS_LLCTL_GEN_VAL(MAX_LINK_RATE, link_rate);
- writel(llctl, &iphy->link_layer_registers->link_layer_control);
+ writel(llctl, &llr->link_layer_control);
- sp_timeouts = readl(&iphy->link_layer_registers->sas_phy_timeouts);
+ sp_timeouts = readl(&llr->sas_phy_timeouts);
/* Clear the default 0x36 (54us) RATE_CHANGE timeout value. */
sp_timeouts &= ~SCU_SAS_PHYTOV_GEN_VAL(RATE_CHANGE, 0xFF);
@@ -222,20 +268,23 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy,
*/
sp_timeouts |= SCU_SAS_PHYTOV_GEN_VAL(RATE_CHANGE, 0x3B);
- writel(sp_timeouts, &iphy->link_layer_registers->sas_phy_timeouts);
+ writel(sp_timeouts, &llr->sas_phy_timeouts);
if (is_a2(ihost->pdev)) {
- /* Program the max ARB time for the PHY to 700us so we inter-operate with
- * the PMC expander which shuts down PHYs if the expander PHY generates too
- * many breaks. This time value will guarantee that the initiator PHY will
- * generate the break.
+ /* Program the max ARB time for the PHY to 700us so we
+ * inter-operate with the PMC expander which shuts down
+ * PHYs if the expander PHY generates too many breaks.
+ * This time value will guarantee that the initiator PHY
+ * will generate the break.
*/
writel(SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME,
- &iphy->link_layer_registers->maximum_arbitration_wait_timer_timeout);
+ &llr->maximum_arbitration_wait_timer_timeout);
}
- /* Disable link layer hang detection, rely on the OS timeout for I/O timeouts. */
- writel(0, &iphy->link_layer_registers->link_layer_hang_detection_timeout);
+ /* Disable link layer hang detection, rely on the OS timeout for
+ * I/O timeouts.
+ */
+ writel(0, &llr->link_layer_hang_detection_timeout);
/* We can exit the initial state to the stopped state */
sci_change_state(&iphy->sm, SCI_PHY_STOPPED);
@@ -1049,24 +1098,25 @@ static void scu_link_layer_stop_protocol_engine(
writel(enable_spinup_value, &iphy->link_layer_registers->notify_enable_spinup_control);
}
-/**
- *
- *
- * This method will start the OOB/SN state machine for this struct isci_phy object.
- */
-static void scu_link_layer_start_oob(
- struct isci_phy *iphy)
+static void scu_link_layer_start_oob(struct isci_phy *iphy)
{
- u32 scu_sas_pcfg_value;
-
- scu_sas_pcfg_value =
- readl(&iphy->link_layer_registers->phy_configuration);
- scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE);
- scu_sas_pcfg_value &=
- ~(SCU_SAS_PCFG_GEN_BIT(OOB_RESET) |
- SCU_SAS_PCFG_GEN_BIT(HARD_RESET));
- writel(scu_sas_pcfg_value,
- &iphy->link_layer_registers->phy_configuration);
+ struct scu_link_layer_registers __iomem *ll = iphy->link_layer_registers;
+ u32 val;
+
+ /** Reset OOB sequence - start */
+ val = readl(&ll->phy_configuration);
+ val &= ~(SCU_SAS_PCFG_GEN_BIT(OOB_RESET) |
+ SCU_SAS_PCFG_GEN_BIT(HARD_RESET));
+ writel(val, &ll->phy_configuration);
+ readl(&ll->phy_configuration); /* flush */
+ /** Reset OOB sequence - end */
+
+ /** Start OOB sequence - start */
+ val = readl(&ll->phy_configuration);
+ val |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE);
+ writel(val, &ll->phy_configuration);
+ readl(&ll->phy_configuration); /* flush */
+ /** Start OOB sequence - end */
}
/**
diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c
index ac7f27749f97..7c6ac58a5c4c 100644
--- a/drivers/scsi/isci/port.c
+++ b/drivers/scsi/isci/port.c
@@ -114,7 +114,7 @@ static u32 sci_port_get_phys(struct isci_port *iport)
* value is returned if the specified port is not valid. When this value is
* returned, no data is copied to the properties output parameter.
*/
-static enum sci_status sci_port_get_properties(struct isci_port *iport,
+enum sci_status sci_port_get_properties(struct isci_port *iport,
struct sci_port_properties *prop)
{
if (!iport || iport->logical_port_index == SCIC_SDS_DUMMY_PORT)
@@ -647,19 +647,26 @@ void sci_port_setup_transports(struct isci_port *iport, u32 device_id)
}
}
-static void sci_port_activate_phy(struct isci_port *iport, struct isci_phy *iphy,
- bool do_notify_user)
+static void sci_port_resume_phy(struct isci_port *iport, struct isci_phy *iphy)
+{
+ sci_phy_resume(iphy);
+ iport->enabled_phy_mask |= 1 << iphy->phy_index;
+}
+
+static void sci_port_activate_phy(struct isci_port *iport,
+ struct isci_phy *iphy,
+ u8 flags)
{
struct isci_host *ihost = iport->owning_controller;
- if (iphy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA)
+ if (iphy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA && (flags & PF_RESUME))
sci_phy_resume(iphy);
iport->active_phy_mask |= 1 << iphy->phy_index;
sci_controller_clear_invalid_phy(ihost, iphy);
- if (do_notify_user == true)
+ if (flags & PF_NOTIFY)
isci_port_link_up(ihost, iport, iphy);
}
@@ -669,14 +676,19 @@ void sci_port_deactivate_phy(struct isci_port *iport, struct isci_phy *iphy,
struct isci_host *ihost = iport->owning_controller;
iport->active_phy_mask &= ~(1 << iphy->phy_index);
+ iport->enabled_phy_mask &= ~(1 << iphy->phy_index);
if (!iport->active_phy_mask)
iport->last_active_phy = iphy->phy_index;
iphy->max_negotiated_speed = SAS_LINK_RATE_UNKNOWN;
- /* Re-assign the phy back to the LP as if it were a narrow port */
- writel(iphy->phy_index,
- &iport->port_pe_configuration_register[iphy->phy_index]);
+ /* Re-assign the phy back to the LP as if it were a narrow port for APC
+ * mode. For MPC mode, the phy will remain in the port.
+ */
+ if (iport->owning_controller->oem_parameters.controller.mode_type ==
+ SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE)
+ writel(iphy->phy_index,
+ &iport->port_pe_configuration_register[iphy->phy_index]);
if (do_notify_user == true)
isci_port_link_down(ihost, iphy, iport);
@@ -701,18 +713,16 @@ static void sci_port_invalid_link_up(struct isci_port *iport, struct isci_phy *i
* sci_port_general_link_up_handler - phy can be assigned to port?
* @sci_port: sci_port object for which has a phy that has gone link up.
* @sci_phy: This is the struct isci_phy object that has gone link up.
- * @do_notify_user: This parameter specifies whether to inform the user (via
- * sci_port_link_up()) as to the fact that a new phy as become ready.
+ * @flags: PF_RESUME, PF_NOTIFY to sci_port_activate_phy
*
- * Determine if this phy can be assigned to this
- * port . If the phy is not a valid PHY for
- * this port then the function will notify the user. A PHY can only be
- * part of a port if it's attached SAS ADDRESS is the same as all other PHYs in
- * the same port. none
+ * Determine if this phy can be assigned to this port . If the phy is
+ * not a valid PHY for this port then the function will notify the user.
+ * A PHY can only be part of a port if it's attached SAS ADDRESS is the
+ * same as all other PHYs in the same port.
*/
static void sci_port_general_link_up_handler(struct isci_port *iport,
- struct isci_phy *iphy,
- bool do_notify_user)
+ struct isci_phy *iphy,
+ u8 flags)
{
struct sci_sas_address port_sas_address;
struct sci_sas_address phy_sas_address;
@@ -730,7 +740,7 @@ static void sci_port_general_link_up_handler(struct isci_port *iport,
iport->active_phy_mask == 0) {
struct sci_base_state_machine *sm = &iport->sm;
- sci_port_activate_phy(iport, iphy, do_notify_user);
+ sci_port_activate_phy(iport, iphy, flags);
if (sm->current_state_id == SCI_PORT_RESETTING)
port_state_machine_change(iport, SCI_PORT_READY);
} else
@@ -781,11 +791,16 @@ bool sci_port_link_detected(
struct isci_phy *iphy)
{
if ((iport->logical_port_index != SCIC_SDS_DUMMY_PORT) &&
- (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) &&
- sci_port_is_wide(iport)) {
- sci_port_invalid_link_up(iport, iphy);
-
- return false;
+ (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA)) {
+ if (sci_port_is_wide(iport)) {
+ sci_port_invalid_link_up(iport, iphy);
+ return false;
+ } else {
+ struct isci_host *ihost = iport->owning_controller;
+ struct isci_port *dst_port = &(ihost->ports[iphy->phy_index]);
+ writel(iphy->phy_index,
+ &dst_port->port_pe_configuration_register[iphy->phy_index]);
+ }
}
return true;
@@ -975,6 +990,13 @@ static void sci_port_ready_substate_waiting_enter(struct sci_base_state_machine
}
}
+static void scic_sds_port_ready_substate_waiting_exit(
+ struct sci_base_state_machine *sm)
+{
+ struct isci_port *iport = container_of(sm, typeof(*iport), sm);
+ sci_port_resume_port_task_scheduler(iport);
+}
+
static void sci_port_ready_substate_operational_enter(struct sci_base_state_machine *sm)
{
u32 index;
@@ -988,13 +1010,13 @@ static void sci_port_ready_substate_operational_enter(struct sci_base_state_mach
writel(iport->physical_port_index,
&iport->port_pe_configuration_register[
iport->phy_table[index]->phy_index]);
+ if (((iport->active_phy_mask^iport->enabled_phy_mask) & (1 << index)) != 0)
+ sci_port_resume_phy(iport, iport->phy_table[index]);
}
}
sci_port_update_viit_entry(iport);
- sci_port_resume_port_task_scheduler(iport);
-
/*
* Post the dummy task for the port so the hardware can schedule
* io correctly
@@ -1061,20 +1083,9 @@ static void sci_port_ready_substate_configuring_enter(struct sci_base_state_mach
if (iport->active_phy_mask == 0) {
isci_port_not_ready(ihost, iport);
- port_state_machine_change(iport,
- SCI_PORT_SUB_WAITING);
- } else if (iport->started_request_count == 0)
- port_state_machine_change(iport,
- SCI_PORT_SUB_OPERATIONAL);
-}
-
-static void sci_port_ready_substate_configuring_exit(struct sci_base_state_machine *sm)
-{
- struct isci_port *iport = container_of(sm, typeof(*iport), sm);
-
- sci_port_suspend_port_task_scheduler(iport);
- if (iport->ready_exit)
- sci_port_invalidate_dummy_remote_node(iport);
+ port_state_machine_change(iport, SCI_PORT_SUB_WAITING);
+ } else
+ port_state_machine_change(iport, SCI_PORT_SUB_OPERATIONAL);
}
enum sci_status sci_port_start(struct isci_port *iport)
@@ -1252,7 +1263,7 @@ enum sci_status sci_port_add_phy(struct isci_port *iport,
if (status != SCI_SUCCESS)
return status;
- sci_port_general_link_up_handler(iport, iphy, true);
+ sci_port_general_link_up_handler(iport, iphy, PF_NOTIFY|PF_RESUME);
iport->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING;
port_state_machine_change(iport, SCI_PORT_SUB_CONFIGURING);
@@ -1262,7 +1273,7 @@ enum sci_status sci_port_add_phy(struct isci_port *iport,
if (status != SCI_SUCCESS)
return status;
- sci_port_general_link_up_handler(iport, iphy, true);
+ sci_port_general_link_up_handler(iport, iphy, PF_NOTIFY);
/* Re-enter the configuring state since this may be the last phy in
* the port.
@@ -1338,13 +1349,13 @@ enum sci_status sci_port_link_up(struct isci_port *iport,
/* Since this is the first phy going link up for the port we
* can just enable it and continue
*/
- sci_port_activate_phy(iport, iphy, true);
+ sci_port_activate_phy(iport, iphy, PF_NOTIFY|PF_RESUME);
port_state_machine_change(iport,
SCI_PORT_SUB_OPERATIONAL);
return SCI_SUCCESS;
case SCI_PORT_SUB_OPERATIONAL:
- sci_port_general_link_up_handler(iport, iphy, true);
+ sci_port_general_link_up_handler(iport, iphy, PF_NOTIFY|PF_RESUME);
return SCI_SUCCESS;
case SCI_PORT_RESETTING:
/* TODO We should make sure that the phy that has gone
@@ -1361,7 +1372,7 @@ enum sci_status sci_port_link_up(struct isci_port *iport,
/* In the resetting state we don't notify the user regarding
* link up and link down notifications.
*/
- sci_port_general_link_up_handler(iport, iphy, false);
+ sci_port_general_link_up_handler(iport, iphy, PF_RESUME);
return SCI_SUCCESS;
default:
dev_warn(sciport_to_dev(iport),
@@ -1584,14 +1595,14 @@ static const struct sci_base_state sci_port_state_table[] = {
},
[SCI_PORT_SUB_WAITING] = {
.enter_state = sci_port_ready_substate_waiting_enter,
+ .exit_state = scic_sds_port_ready_substate_waiting_exit,
},
[SCI_PORT_SUB_OPERATIONAL] = {
.enter_state = sci_port_ready_substate_operational_enter,
.exit_state = sci_port_ready_substate_operational_exit
},
[SCI_PORT_SUB_CONFIGURING] = {
- .enter_state = sci_port_ready_substate_configuring_enter,
- .exit_state = sci_port_ready_substate_configuring_exit
+ .enter_state = sci_port_ready_substate_configuring_enter
},
[SCI_PORT_RESETTING] = {
.exit_state = sci_port_resetting_state_exit
@@ -1609,6 +1620,7 @@ void sci_port_construct(struct isci_port *iport, u8 index,
iport->logical_port_index = SCIC_SDS_DUMMY_PORT;
iport->physical_port_index = index;
iport->active_phy_mask = 0;
+ iport->enabled_phy_mask = 0;
iport->last_active_phy = 0;
iport->ready_exit = false;
diff --git a/drivers/scsi/isci/port.h b/drivers/scsi/isci/port.h
index cb5ffbc38603..08116090eb70 100644
--- a/drivers/scsi/isci/port.h
+++ b/drivers/scsi/isci/port.h
@@ -63,6 +63,9 @@
#define SCIC_SDS_DUMMY_PORT 0xFF
+#define PF_NOTIFY (1 << 0)
+#define PF_RESUME (1 << 1)
+
struct isci_phy;
struct isci_host;
@@ -83,6 +86,8 @@ enum isci_status {
* @logical_port_index: software port index
* @physical_port_index: hardware port index
* @active_phy_mask: identifies phy members
+ * @enabled_phy_mask: phy mask for the port
+ * that are already part of the port
* @reserved_tag:
* @reserved_rni: reserver for port task scheduler workaround
* @started_request_count: reference count for outstanding commands
@@ -104,6 +109,7 @@ struct isci_port {
u8 logical_port_index;
u8 physical_port_index;
u8 active_phy_mask;
+ u8 enabled_phy_mask;
u8 last_active_phy;
u16 reserved_rni;
u16 reserved_tag;
@@ -250,6 +256,10 @@ bool sci_port_link_detected(
struct isci_port *iport,
struct isci_phy *iphy);
+enum sci_status sci_port_get_properties(
+ struct isci_port *iport,
+ struct sci_port_properties *prop);
+
enum sci_status sci_port_link_up(struct isci_port *iport,
struct isci_phy *iphy);
enum sci_status sci_port_link_down(struct isci_port *iport,
diff --git a/drivers/scsi/isci/port_config.c b/drivers/scsi/isci/port_config.c
index 38a99d281141..6d1e9544cbe5 100644
--- a/drivers/scsi/isci/port_config.c
+++ b/drivers/scsi/isci/port_config.c
@@ -57,7 +57,7 @@
#define SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT (10)
#define SCIC_SDS_APC_RECONFIGURATION_TIMEOUT (10)
-#define SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION (100)
+#define SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION (250)
enum SCIC_SDS_APC_ACTIVITY {
SCIC_SDS_APC_SKIP_PHY,
@@ -466,6 +466,23 @@ sci_apc_agent_validate_phy_configuration(struct isci_host *ihost,
return sci_port_configuration_agent_validate_ports(ihost, port_agent);
}
+/*
+ * This routine will restart the automatic port configuration timeout
+ * timer for the next time period. This could be caused by either a link
+ * down event or a link up event where we can not yet tell to which a phy
+ * belongs.
+ */
+static void sci_apc_agent_start_timer(
+ struct sci_port_configuration_agent *port_agent,
+ u32 timeout)
+{
+ if (port_agent->timer_pending)
+ sci_del_timer(&port_agent->timer);
+
+ port_agent->timer_pending = true;
+ sci_mod_timer(&port_agent->timer, timeout);
+}
+
static void sci_apc_agent_configure_ports(struct isci_host *ihost,
struct sci_port_configuration_agent *port_agent,
struct isci_phy *iphy,
@@ -565,17 +582,8 @@ static void sci_apc_agent_configure_ports(struct isci_host *ihost,
break;
case SCIC_SDS_APC_START_TIMER:
- /*
- * This can occur for either a link down event, or a link
- * up event where we cannot yet tell the port to which a
- * phy belongs.
- */
- if (port_agent->timer_pending)
- sci_del_timer(&port_agent->timer);
-
- port_agent->timer_pending = true;
- sci_mod_timer(&port_agent->timer,
- SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION);
+ sci_apc_agent_start_timer(port_agent,
+ SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION);
break;
case SCIC_SDS_APC_SKIP_PHY:
@@ -607,7 +615,8 @@ static void sci_apc_agent_link_up(struct isci_host *ihost,
if (!iport) {
/* the phy is not the part of this port */
port_agent->phy_ready_mask |= 1 << phy_index;
- sci_apc_agent_configure_ports(ihost, port_agent, iphy, true);
+ sci_apc_agent_start_timer(port_agent,
+ SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION);
} else {
/* the phy is already the part of the port */
u32 port_state = iport->sm.current_state_id;
diff --git a/drivers/scsi/isci/probe_roms.c b/drivers/scsi/isci/probe_roms.c
index b5f4341de243..9b8117b9d756 100644
--- a/drivers/scsi/isci/probe_roms.c
+++ b/drivers/scsi/isci/probe_roms.c
@@ -147,7 +147,7 @@ struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmw
memcpy(orom, fw->data, fw->size);
- if (is_c0(pdev))
+ if (is_c0(pdev) || is_c1(pdev))
goto out;
/*
diff --git a/drivers/scsi/isci/probe_roms.h b/drivers/scsi/isci/probe_roms.h
index 2c75248ca326..bb0e9d4d97c9 100644
--- a/drivers/scsi/isci/probe_roms.h
+++ b/drivers/scsi/isci/probe_roms.h
@@ -152,7 +152,7 @@ struct sci_user_parameters {
#define MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT 4
struct sci_oem_params;
-int sci_oem_parameters_validate(struct sci_oem_params *oem);
+int sci_oem_parameters_validate(struct sci_oem_params *oem, u8 version);
struct isci_orom;
struct isci_orom *isci_request_oprom(struct pci_dev *pdev);
@@ -191,6 +191,11 @@ struct isci_oem_hdr {
0x1a, 0x04, 0xc6)
#define ISCI_EFI_VAR_NAME "RstScuO"
+#define ISCI_ROM_VER_1_0 0x10
+#define ISCI_ROM_VER_1_1 0x11
+#define ISCI_ROM_VER_1_3 0x13
+#define ISCI_ROM_VER_LATEST ISCI_ROM_VER_1_3
+
/* Allowed PORT configuration modes APC Automatic PORT configuration mode is
* defined by the OEM configuration parameters providing no PHY_MASK parameters
* for any PORT. i.e. There are no phys assigned to any of the ports at start.
@@ -220,8 +225,86 @@ struct sci_oem_params {
struct {
uint8_t mode_type;
uint8_t max_concurr_spin_up;
- uint8_t do_enable_ssc;
- uint8_t reserved;
+ /*
+ * This bitfield indicates the OEM's desired default Tx
+ * Spread Spectrum Clocking (SSC) settings for SATA and SAS.
+ * NOTE: Default SSC Modulation Frequency is 31.5KHz.
+ */
+ union {
+ struct {
+ /*
+ * NOTE: Max spread for SATA is +0 / -5000 PPM.
+ * Down-spreading SSC (only method allowed for SATA):
+ * SATA SSC Tx Disabled = 0x0
+ * SATA SSC Tx at +0 / -1419 PPM Spread = 0x2
+ * SATA SSC Tx at +0 / -2129 PPM Spread = 0x3
+ * SATA SSC Tx at +0 / -4257 PPM Spread = 0x6
+ * SATA SSC Tx at +0 / -4967 PPM Spread = 0x7
+ */
+ uint8_t ssc_sata_tx_spread_level:4;
+ /*
+ * SAS SSC Tx Disabled = 0x0
+ *
+ * NOTE: Max spread for SAS down-spreading +0 /
+ * -2300 PPM
+ * Down-spreading SSC:
+ * SAS SSC Tx at +0 / -1419 PPM Spread = 0x2
+ * SAS SSC Tx at +0 / -2129 PPM Spread = 0x3
+ *
+ * NOTE: Max spread for SAS center-spreading +2300 /
+ * -2300 PPM
+ * Center-spreading SSC:
+ * SAS SSC Tx at +1064 / -1064 PPM Spread = 0x3
+ * SAS SSC Tx at +2129 / -2129 PPM Spread = 0x6
+ */
+ uint8_t ssc_sas_tx_spread_level:3;
+ /*
+ * NOTE: Refer to the SSC section of the SAS 2.x
+ * Specification for proper setting of this field.
+ * For standard SAS Initiator SAS PHY operation it
+ * should be 0 for Down-spreading.
+ * SAS SSC Tx spread type:
+ * Down-spreading SSC = 0
+ * Center-spreading SSC = 1
+ */
+ uint8_t ssc_sas_tx_type:1;
+ };
+ uint8_t do_enable_ssc;
+ };
+ /*
+ * This field indicates length of the SAS/SATA cable between
+ * host and device.
+ * This field is used make relationship between analog
+ * parameters of the phy in the silicon and length of the cable.
+ * Supported cable attenuation levels:
+ * "short"- up to 3m, "medium"-3m to 6m, and "long"- more than
+ * 6m.
+ *
+ * This is bit mask field:
+ *
+ * BIT: (MSB) 7 6 5 4
+ * ASSIGNMENT: <phy3><phy2><phy1><phy0> - Medium cable
+ * length assignment
+ * BIT: 3 2 1 0 (LSB)
+ * ASSIGNMENT: <phy3><phy2><phy1><phy0> - Long cable length
+ * assignment
+ *
+ * BITS 7-4 are set when the cable length is assigned to medium
+ * BITS 3-0 are set when the cable length is assigned to long
+ *
+ * The BIT positions are clear when the cable length is
+ * assigned to short.
+ *
+ * Setting the bits for both long and medium cable length is
+ * undefined.
+ *
+ * A value of 0x84 would assign
+ * phy3 - medium
+ * phy2 - long
+ * phy1 - short
+ * phy0 - short
+ */
+ uint8_t cable_selection_mask;
} controller;
struct {
diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c
index b207cd3b15a0..dd74b6ceeb82 100644
--- a/drivers/scsi/isci/remote_device.c
+++ b/drivers/scsi/isci/remote_device.c
@@ -53,6 +53,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <scsi/sas.h>
+#include <linux/bitops.h>
#include "isci.h"
#include "port.h"
#include "remote_device.h"
@@ -1101,6 +1102,7 @@ static enum sci_status sci_remote_device_da_construct(struct isci_port *iport,
struct isci_remote_device *idev)
{
enum sci_status status;
+ struct sci_port_properties properties;
struct domain_device *dev = idev->domain_dev;
sci_remote_device_construct(iport, idev);
@@ -1110,6 +1112,11 @@ static enum sci_status sci_remote_device_da_construct(struct isci_port *iport,
* entries will be needed to store the remote node.
*/
idev->is_direct_attached = true;
+
+ sci_port_get_properties(iport, &properties);
+ /* Get accurate port width from port's phy mask for a DA device. */
+ idev->device_port_width = hweight32(properties.phy_mask);
+
status = sci_controller_allocate_remote_node_context(iport->owning_controller,
idev,
&idev->rnc.remote_node_index);
@@ -1125,9 +1132,6 @@ static enum sci_status sci_remote_device_da_construct(struct isci_port *iport,
idev->connection_rate = sci_port_get_max_allowed_speed(iport);
- /* / @todo Should I assign the port width by reading all of the phys on the port? */
- idev->device_port_width = 1;
-
return SCI_SUCCESS;
}
diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c
index 66ad3dc89498..f5a3f7d2bdab 100644
--- a/drivers/scsi/isci/task.c
+++ b/drivers/scsi/isci/task.c
@@ -496,7 +496,7 @@ static int isci_task_execute_tmf(struct isci_host *ihost,
}
}
- isci_print_tmf(tmf);
+ isci_print_tmf(ihost, tmf);
if (tmf->status == SCI_SUCCESS)
ret = TMF_RESP_FUNC_COMPLETE;
diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h
index bc78c0a41d5c..1b27b3797c6c 100644
--- a/drivers/scsi/isci/task.h
+++ b/drivers/scsi/isci/task.h
@@ -106,7 +106,6 @@ struct isci_tmf {
} resp;
unsigned char lun[8];
u16 io_tag;
- struct isci_remote_device *device;
enum isci_tmf_function_codes tmf_code;
int status;
@@ -120,10 +119,10 @@ struct isci_tmf {
};
-static inline void isci_print_tmf(struct isci_tmf *tmf)
+static inline void isci_print_tmf(struct isci_host *ihost, struct isci_tmf *tmf)
{
if (SAS_PROTOCOL_SATA == tmf->proto)
- dev_dbg(&tmf->device->isci_port->isci_host->pdev->dev,
+ dev_dbg(&ihost->pdev->dev,
"%s: status = %x\n"
"tmf->resp.d2h_fis.status = %x\n"
"tmf->resp.d2h_fis.error = %x\n",
@@ -132,7 +131,7 @@ static inline void isci_print_tmf(struct isci_tmf *tmf)
tmf->resp.d2h_fis.status,
tmf->resp.d2h_fis.error);
else
- dev_dbg(&tmf->device->isci_port->isci_host->pdev->dev,
+ dev_dbg(&ihost->pdev->dev,
"%s: status = %x\n"
"tmf->resp.resp_iu.data_present = %x\n"
"tmf->resp.resp_iu.status = %x\n"
diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index 7269e928824a..1d1b0c9da29b 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -61,7 +61,7 @@ static void fc_disc_restart(struct fc_disc *);
* Locking Note: This function expects that the lport mutex is locked before
* calling it.
*/
-void fc_disc_stop_rports(struct fc_disc *disc)
+static void fc_disc_stop_rports(struct fc_disc *disc)
{
struct fc_lport *lport;
struct fc_rport_priv *rdata;
@@ -682,7 +682,7 @@ static int fc_disc_single(struct fc_lport *lport, struct fc_disc_port *dp)
* fc_disc_stop() - Stop discovery for a given lport
* @lport: The local port that discovery should stop on
*/
-void fc_disc_stop(struct fc_lport *lport)
+static void fc_disc_stop(struct fc_lport *lport)
{
struct fc_disc *disc = &lport->disc;
@@ -698,7 +698,7 @@ void fc_disc_stop(struct fc_lport *lport)
* This function will block until discovery has been
* completely stopped and all rports have been deleted.
*/
-void fc_disc_stop_final(struct fc_lport *lport)
+static void fc_disc_stop_final(struct fc_lport *lport)
{
fc_disc_stop(lport);
lport->tt.rport_flush_queue();
diff --git a/drivers/scsi/libfc/fc_elsct.c b/drivers/scsi/libfc/fc_elsct.c
index fb9161dc4ca6..e17a28d324d0 100644
--- a/drivers/scsi/libfc/fc_elsct.c
+++ b/drivers/scsi/libfc/fc_elsct.c
@@ -28,6 +28,7 @@
#include <scsi/fc/fc_els.h>
#include <scsi/libfc.h>
#include <scsi/fc_encode.h>
+#include "fc_libfc.h"
/**
* fc_elsct_send() - Send an ELS or CT frame
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 9de9db27e874..4d70d96fa5dc 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -91,7 +91,7 @@ struct fc_exch_pool {
* It manages the allocation of exchange IDs.
*/
struct fc_exch_mgr {
- struct fc_exch_pool *pool;
+ struct fc_exch_pool __percpu *pool;
mempool_t *ep_pool;
enum fc_class class;
struct kref kref;
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 221875ec3d7c..f607314810ac 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -155,6 +155,7 @@ static struct fc_fcp_pkt *fc_fcp_pkt_alloc(struct fc_lport *lport, gfp_t gfp)
fsp->xfer_ddp = FC_XID_UNKNOWN;
atomic_set(&fsp->ref_cnt, 1);
init_timer(&fsp->timer);
+ fsp->timer.data = (unsigned long)fsp;
INIT_LIST_HEAD(&fsp->list);
spin_lock_init(&fsp->scsi_pkt_lock);
}
@@ -1850,9 +1851,6 @@ int fc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc_cmd)
}
put_cpu();
- init_timer(&fsp->timer);
- fsp->timer.data = (unsigned long)fsp;
-
/*
* send it to the lower layer
* if we get -1 return then put the request in the pending
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index e77094a587ed..83750ebb527f 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -677,7 +677,8 @@ EXPORT_SYMBOL(fc_set_mfs);
* @lport: The local port receiving the event
* @event: The discovery event
*/
-void fc_lport_disc_callback(struct fc_lport *lport, enum fc_disc_event event)
+static void fc_lport_disc_callback(struct fc_lport *lport,
+ enum fc_disc_event event)
{
switch (event) {
case DISC_EV_SUCCESS:
@@ -1568,7 +1569,7 @@ EXPORT_SYMBOL(fc_lport_flogi_resp);
* Locking Note: The lport lock is expected to be held before calling
* this routine.
*/
-void fc_lport_enter_flogi(struct fc_lport *lport)
+static void fc_lport_enter_flogi(struct fc_lport *lport)
{
struct fc_frame *fp;
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index b9e434844a69..83aa1efec875 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -391,7 +391,7 @@ static void fc_rport_work(struct work_struct *work)
* If it appears we are already logged in, ADISC is used to verify
* the setup.
*/
-int fc_rport_login(struct fc_rport_priv *rdata)
+static int fc_rport_login(struct fc_rport_priv *rdata)
{
mutex_lock(&rdata->rp_mutex);
@@ -451,7 +451,7 @@ static void fc_rport_enter_delete(struct fc_rport_priv *rdata,
* function will hold the rport lock, call an _enter_*
* function and then unlock the rport.
*/
-int fc_rport_logoff(struct fc_rport_priv *rdata)
+static int fc_rport_logoff(struct fc_rport_priv *rdata)
{
mutex_lock(&rdata->rp_mutex);
@@ -653,8 +653,8 @@ static int fc_rport_login_complete(struct fc_rport_priv *rdata,
* @fp: The FLOGI response frame
* @rp_arg: The remote port that received the FLOGI response
*/
-void fc_rport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
- void *rp_arg)
+static void fc_rport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
+ void *rp_arg)
{
struct fc_rport_priv *rdata = rp_arg;
struct fc_lport *lport = rdata->local_port;
@@ -1520,7 +1520,7 @@ reject:
*
* Locking Note: Called with the lport lock held.
*/
-void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp)
+static void fc_rport_recv_req(struct fc_lport *lport, struct fc_frame *fp)
{
struct fc_seq_els_data els_data;
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 5c1776406c96..15eefa1d61fd 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -306,19 +306,22 @@ mega_query_adapter(adapter_t *adapter)
adapter->host->sg_tablesize = adapter->sglen;
- /* use HP firmware and bios version encoding */
+ /* use HP firmware and bios version encoding
+ Note: fw_version[0|1] and bios_version[0|1] were originally shifted
+ right 8 bits making them zero. This 0 value was hardcoded to fix
+ sparse warnings. */
if (adapter->product_info.subsysvid == HP_SUBSYS_VID) {
sprintf (adapter->fw_version, "%c%d%d.%d%d",
adapter->product_info.fw_version[2],
- adapter->product_info.fw_version[1] >> 8,
+ 0,
adapter->product_info.fw_version[1] & 0x0f,
- adapter->product_info.fw_version[0] >> 8,
+ 0,
adapter->product_info.fw_version[0] & 0x0f);
sprintf (adapter->bios_version, "%c%d%d.%d%d",
adapter->product_info.bios_version[2],
- adapter->product_info.bios_version[1] >> 8,
+ 0,
adapter->product_info.bios_version[1] & 0x0f,
- adapter->product_info.bios_version[0] >> 8,
+ 0,
adapter->product_info.bios_version[0] & 0x0f);
} else {
memcpy(adapter->fw_version,
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index dd94c7d574fb..e5f416f8042d 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -33,9 +33,9 @@
/*
* MegaRAID SAS Driver meta data
*/
-#define MEGASAS_VERSION "00.00.06.12-rc1"
-#define MEGASAS_RELDATE "Oct. 5, 2011"
-#define MEGASAS_EXT_VERSION "Wed. Oct. 5 17:00:00 PDT 2011"
+#define MEGASAS_VERSION "00.00.06.14-rc1"
+#define MEGASAS_RELDATE "Jan. 6, 2012"
+#define MEGASAS_EXT_VERSION "Fri. Jan. 6 17:00:00 PDT 2012"
/*
* Device IDs
@@ -773,7 +773,6 @@ struct megasas_ctrl_info {
#define MFI_OB_INTR_STATUS_MASK 0x00000002
#define MFI_POLL_TIMEOUT_SECS 60
-#define MEGASAS_COMPLETION_TIMER_INTERVAL (HZ/10)
#define MFI_REPLY_1078_MESSAGE_INTERRUPT 0x80000000
#define MFI_REPLY_GEN2_MESSAGE_INTERRUPT 0x00000001
@@ -1353,7 +1352,6 @@ struct megasas_instance {
u32 mfiStatus;
u32 last_seq_num;
- struct timer_list io_completion_timer;
struct list_head internal_reset_pending_q;
/* Ptr to hba specific information */
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index 29a994f9c4f1..8b300be44284 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* FILE: megaraid_sas_base.c
- * Version : v00.00.06.12-rc1
+ * Version : v00.00.06.14-rc1
*
* Authors: LSI Corporation
* Sreenivas Bagalkote
@@ -59,14 +59,6 @@
#include "megaraid_sas.h"
/*
- * poll_mode_io:1- schedule complete completion from q cmd
- */
-static unsigned int poll_mode_io;
-module_param_named(poll_mode_io, poll_mode_io, int, 0);
-MODULE_PARM_DESC(poll_mode_io,
- "Complete cmds from IO path, (default=0)");
-
-/*
* Number of sectors per IO command
* Will be set in megasas_init_mfi if user does not provide
*/
@@ -1439,11 +1431,6 @@ megasas_build_and_issue_cmd(struct megasas_instance *instance,
instance->instancet->fire_cmd(instance, cmd->frame_phys_addr,
cmd->frame_count-1, instance->reg_set);
- /*
- * Check if we have pend cmds to be completed
- */
- if (poll_mode_io && atomic_read(&instance->fw_outstanding))
- tasklet_schedule(&instance->isr_tasklet);
return 0;
out_return_cmd:
@@ -3370,47 +3357,6 @@ fail_fw_init:
return -EINVAL;
}
-/**
- * megasas_start_timer - Initializes a timer object
- * @instance: Adapter soft state
- * @timer: timer object to be initialized
- * @fn: timer function
- * @interval: time interval between timer function call
- */
-static inline void
-megasas_start_timer(struct megasas_instance *instance,
- struct timer_list *timer,
- void *fn, unsigned long interval)
-{
- init_timer(timer);
- timer->expires = jiffies + interval;
- timer->data = (unsigned long)instance;
- timer->function = fn;
- add_timer(timer);
-}
-
-/**
- * megasas_io_completion_timer - Timer fn
- * @instance_addr: Address of adapter soft state
- *
- * Schedules tasklet for cmd completion
- * if poll_mode_io is set
- */
-static void
-megasas_io_completion_timer(unsigned long instance_addr)
-{
- struct megasas_instance *instance =
- (struct megasas_instance *)instance_addr;
-
- if (atomic_read(&instance->fw_outstanding))
- tasklet_schedule(&instance->isr_tasklet);
-
- /* Restart timer */
- if (poll_mode_io)
- mod_timer(&instance->io_completion_timer,
- jiffies + MEGASAS_COMPLETION_TIMER_INTERVAL);
-}
-
static u32
megasas_init_adapter_mfi(struct megasas_instance *instance)
{
@@ -3638,11 +3584,6 @@ static int megasas_init_fw(struct megasas_instance *instance)
tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet,
(unsigned long)instance);
- /* Initialize the cmd completion timer */
- if (poll_mode_io)
- megasas_start_timer(instance, &instance->io_completion_timer,
- megasas_io_completion_timer,
- MEGASAS_COMPLETION_TIMER_INTERVAL);
return 0;
fail_init_adapter:
@@ -4369,9 +4310,6 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state)
host = instance->host;
instance->unload = 1;
- if (poll_mode_io)
- del_timer_sync(&instance->io_completion_timer);
-
megasas_flush_cache(instance);
megasas_shutdown_controller(instance, MR_DCMD_HIBERNATE_SHUTDOWN);
@@ -4511,12 +4449,6 @@ megasas_resume(struct pci_dev *pdev)
}
instance->instancet->enable_intr(instance->reg_set);
-
- /* Initialize the cmd completion timer */
- if (poll_mode_io)
- megasas_start_timer(instance, &instance->io_completion_timer,
- megasas_io_completion_timer,
- MEGASAS_COMPLETION_TIMER_INTERVAL);
instance->unload = 0;
/*
@@ -4570,9 +4502,6 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev)
host = instance->host;
fusion = instance->ctrl_context;
- if (poll_mode_io)
- del_timer_sync(&instance->io_completion_timer);
-
scsi_remove_host(instance->host);
megasas_flush_cache(instance);
megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
@@ -4773,6 +4702,8 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
memcpy(cmd->frame, ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE);
cmd->frame->hdr.context = cmd->index;
cmd->frame->hdr.pad_0 = 0;
+ cmd->frame->hdr.flags &= ~(MFI_FRAME_IEEE | MFI_FRAME_SGL64 |
+ MFI_FRAME_SENSE64);
/*
* The management interface between applications and the fw uses
@@ -5219,60 +5150,6 @@ megasas_sysfs_set_dbg_lvl(struct device_driver *dd, const char *buf, size_t coun
static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUSR, megasas_sysfs_show_dbg_lvl,
megasas_sysfs_set_dbg_lvl);
-static ssize_t
-megasas_sysfs_show_poll_mode_io(struct device_driver *dd, char *buf)
-{
- return sprintf(buf, "%u\n", poll_mode_io);
-}
-
-static ssize_t
-megasas_sysfs_set_poll_mode_io(struct device_driver *dd,
- const char *buf, size_t count)
-{
- int retval = count;
- int tmp = poll_mode_io;
- int i;
- struct megasas_instance *instance;
-
- if (sscanf(buf, "%u", &poll_mode_io) < 1) {
- printk(KERN_ERR "megasas: could not set poll_mode_io\n");
- retval = -EINVAL;
- }
-
- /*
- * Check if poll_mode_io is already set or is same as previous value
- */
- if ((tmp && poll_mode_io) || (tmp == poll_mode_io))
- goto out;
-
- if (poll_mode_io) {
- /*
- * Start timers for all adapters
- */
- for (i = 0; i < megasas_mgmt_info.max_index; i++) {
- instance = megasas_mgmt_info.instance[i];
- if (instance) {
- megasas_start_timer(instance,
- &instance->io_completion_timer,
- megasas_io_completion_timer,
- MEGASAS_COMPLETION_TIMER_INTERVAL);
- }
- }
- } else {
- /*
- * Delete timers for all adapters
- */
- for (i = 0; i < megasas_mgmt_info.max_index; i++) {
- instance = megasas_mgmt_info.instance[i];
- if (instance)
- del_timer_sync(&instance->io_completion_timer);
- }
- }
-
-out:
- return retval;
-}
-
static void
megasas_aen_polling(struct work_struct *work)
{
@@ -5502,11 +5379,6 @@ megasas_aen_polling(struct work_struct *work)
kfree(ev);
}
-
-static DRIVER_ATTR(poll_mode_io, S_IRUGO|S_IWUSR,
- megasas_sysfs_show_poll_mode_io,
- megasas_sysfs_set_poll_mode_io);
-
/**
* megasas_init - Driver load entry point
*/
@@ -5566,11 +5438,6 @@ static int __init megasas_init(void)
if (rval)
goto err_dcf_dbg_lvl;
rval = driver_create_file(&megasas_pci_driver.driver,
- &driver_attr_poll_mode_io);
- if (rval)
- goto err_dcf_poll_mode_io;
-
- rval = driver_create_file(&megasas_pci_driver.driver,
&driver_attr_support_device_change);
if (rval)
goto err_dcf_support_device_change;
@@ -5579,10 +5446,6 @@ static int __init megasas_init(void)
err_dcf_support_device_change:
driver_remove_file(&megasas_pci_driver.driver,
- &driver_attr_poll_mode_io);
-
-err_dcf_poll_mode_io:
- driver_remove_file(&megasas_pci_driver.driver,
&driver_attr_dbg_lvl);
err_dcf_dbg_lvl:
driver_remove_file(&megasas_pci_driver.driver,
@@ -5607,8 +5470,6 @@ err_pcidrv:
static void __exit megasas_exit(void)
{
driver_remove_file(&megasas_pci_driver.driver,
- &driver_attr_poll_mode_io);
- driver_remove_file(&megasas_pci_driver.driver,
&driver_attr_dbg_lvl);
driver_remove_file(&megasas_pci_driver.driver,
&driver_attr_support_poll_for_event);
diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c
index 5255dd688aca..294abb0defa6 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fp.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fp.c
@@ -282,7 +282,9 @@ u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow,
else {
*pDevHandle = MR_PD_INVALID; /* set dev handle as invalid. */
if ((raid->level >= 5) &&
- (instance->pdev->device != PCI_DEVICE_ID_LSI_INVADER))
+ ((instance->pdev->device != PCI_DEVICE_ID_LSI_INVADER) ||
+ (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER &&
+ raid->regTypeReqOnRead != REGION_TYPE_UNUSED)))
pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE;
else if (raid->level == 1) {
/* Get alternate Pd. */
diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c
index f6a50c98c36f..002924963cd8 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 ca86721a71b9..b61a753eb896 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/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h
index 22a3ff02e48a..bfe68545203f 100644
--- a/drivers/scsi/qla4xxx/ql4_def.h
+++ b/drivers/scsi/qla4xxx/ql4_def.h
@@ -150,6 +150,8 @@
#define QL4_SESS_RECOVERY_TMO 120 /* iSCSI session */
/* recovery timeout */
+#define MSB(x) ((uint8_t)((uint16_t)(x) >> 8))
+#define LSW(x) ((uint16_t)(x))
#define LSDW(x) ((u32)((u64)(x)))
#define MSDW(x) ((u32)((((u64)(x)) >> 16) >> 16))
@@ -671,6 +673,7 @@ struct scsi_qla_host {
uint16_t pri_ddb_idx;
uint16_t sec_ddb_idx;
int is_reset;
+ uint16_t temperature;
};
struct ql4_task_data {
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
index 1bdfa8120ac8..90614f38b55d 100644
--- a/drivers/scsi/qla4xxx/ql4_init.c
+++ b/drivers/scsi/qla4xxx/ql4_init.c
@@ -697,6 +697,9 @@ int qla4xxx_start_firmware(struct scsi_qla_host *ha)
writel(set_rmask(CSR_SCSI_PROCESSOR_INTR),
&ha->reg->ctrl_status);
readl(&ha->reg->ctrl_status);
+ writel(set_rmask(CSR_SCSI_COMPLETION_INTR),
+ &ha->reg->ctrl_status);
+ readl(&ha->reg->ctrl_status);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
if (qla4xxx_get_firmware_state(ha) == QLA_SUCCESS) {
DEBUG2(printk("scsi%ld: %s: Get firmware "
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
index c2593782fbbe..e1e66a45e4d0 100644
--- a/drivers/scsi/qla4xxx/ql4_mbx.c
+++ b/drivers/scsi/qla4xxx/ql4_mbx.c
@@ -219,6 +219,13 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
ha->mailbox_timeout_count++;
mbx_sts[0] = (-1);
set_bit(DPC_RESET_HA, &ha->dpc_flags);
+ if (is_qla8022(ha)) {
+ ql4_printk(KERN_INFO, ha,
+ "disabling pause transmit on port 0 & 1.\n");
+ qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x98,
+ CRB_NIU_XG_PAUSE_CTL_P0 |
+ CRB_NIU_XG_PAUSE_CTL_P1);
+ }
goto mbox_exit;
}
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c
index 8d6bc1b2ff17..78f1111158d7 100644
--- a/drivers/scsi/qla4xxx/ql4_nx.c
+++ b/drivers/scsi/qla4xxx/ql4_nx.c
@@ -1875,6 +1875,11 @@ exit:
int qla4_8xxx_load_risc(struct scsi_qla_host *ha)
{
int retval;
+
+ /* clear the interrupt */
+ writel(0, &ha->qla4_8xxx_reg->host_int);
+ readl(&ha->qla4_8xxx_reg->host_int);
+
retval = qla4_8xxx_device_state_handler(ha);
if (retval == QLA_SUCCESS && !test_bit(AF_INIT_DONE, &ha->flags))
diff --git a/drivers/scsi/qla4xxx/ql4_nx.h b/drivers/scsi/qla4xxx/ql4_nx.h
index 35376a1c3f1b..dc45ac923691 100644
--- a/drivers/scsi/qla4xxx/ql4_nx.h
+++ b/drivers/scsi/qla4xxx/ql4_nx.h
@@ -19,12 +19,28 @@
#define PHAN_PEG_RCV_INITIALIZED 0xff01
/*CRB_RELATED*/
-#define QLA82XX_CRB_BASE QLA82XX_CAM_RAM(0x200)
-#define QLA82XX_REG(X) (QLA82XX_CRB_BASE+(X))
-
+#define QLA82XX_CRB_BASE (QLA82XX_CAM_RAM(0x200))
+#define QLA82XX_REG(X) (QLA82XX_CRB_BASE+(X))
#define CRB_CMDPEG_STATE QLA82XX_REG(0x50)
#define CRB_RCVPEG_STATE QLA82XX_REG(0x13c)
#define CRB_DMA_SHIFT QLA82XX_REG(0xcc)
+#define CRB_TEMP_STATE QLA82XX_REG(0x1b4)
+
+#define qla82xx_get_temp_val(x) ((x) >> 16)
+#define qla82xx_get_temp_state(x) ((x) & 0xffff)
+#define qla82xx_encode_temp(val, state) (((val) << 16) | (state))
+
+/*
+ * Temperature control.
+ */
+enum {
+ QLA82XX_TEMP_NORMAL = 0x1, /* Normal operating range */
+ QLA82XX_TEMP_WARN, /* Sound alert, temperature getting high */
+ QLA82XX_TEMP_PANIC /* Fatal error, hardware has shut down. */
+};
+
+#define CRB_NIU_XG_PAUSE_CTL_P0 0x1
+#define CRB_NIU_XG_PAUSE_CTL_P1 0x8
#define QLA82XX_HW_H0_CH_HUB_ADR 0x05
#define QLA82XX_HW_H1_CH_HUB_ADR 0x0E
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index ec393a00c038..ce6d3b7f0c61 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -35,43 +35,44 @@ static struct kmem_cache *srb_cachep;
int ql4xdisablesysfsboot = 1;
module_param(ql4xdisablesysfsboot, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(ql4xdisablesysfsboot,
- "Set to disable exporting boot targets to sysfs\n"
- " 0 - Export boot targets\n"
- " 1 - Do not export boot targets (Default)");
+ " Set to disable exporting boot targets to sysfs.\n"
+ "\t\t 0 - Export boot targets\n"
+ "\t\t 1 - Do not export boot targets (Default)");
int ql4xdontresethba = 0;
module_param(ql4xdontresethba, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(ql4xdontresethba,
- "Don't reset the HBA for driver recovery \n"
- " 0 - It will reset HBA (Default)\n"
- " 1 - It will NOT reset HBA");
+ " Don't reset the HBA for driver recovery.\n"
+ "\t\t 0 - It will reset HBA (Default)\n"
+ "\t\t 1 - It will NOT reset HBA");
-int ql4xextended_error_logging = 0; /* 0 = off, 1 = log errors */
+int ql4xextended_error_logging;
module_param(ql4xextended_error_logging, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(ql4xextended_error_logging,
- "Option to enable extended error logging, "
- "Default is 0 - no logging, 1 - debug logging");
+ " Option to enable extended error logging.\n"
+ "\t\t 0 - no logging (Default)\n"
+ "\t\t 2 - debug logging");
int ql4xenablemsix = 1;
module_param(ql4xenablemsix, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql4xenablemsix,
- "Set to enable MSI or MSI-X interrupt mechanism.\n"
- " 0 = enable INTx interrupt mechanism.\n"
- " 1 = enable MSI-X interrupt mechanism (Default).\n"
- " 2 = enable MSI interrupt mechanism.");
+ " Set to enable MSI or MSI-X interrupt mechanism.\n"
+ "\t\t 0 = enable INTx interrupt mechanism.\n"
+ "\t\t 1 = enable MSI-X interrupt mechanism (Default).\n"
+ "\t\t 2 = enable MSI interrupt mechanism.");
#define QL4_DEF_QDEPTH 32
static int ql4xmaxqdepth = QL4_DEF_QDEPTH;
module_param(ql4xmaxqdepth, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(ql4xmaxqdepth,
- "Maximum queue depth to report for target devices.\n"
- " Default: 32.");
+ " Maximum queue depth to report for target devices.\n"
+ "\t\t Default: 32.");
static int ql4xsess_recovery_tmo = QL4_SESS_RECOVERY_TMO;
module_param(ql4xsess_recovery_tmo, int, S_IRUGO);
MODULE_PARM_DESC(ql4xsess_recovery_tmo,
"Target Session Recovery Timeout.\n"
- " Default: 120 sec.");
+ "\t\t Default: 120 sec.");
static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha);
/*
@@ -1630,7 +1631,9 @@ void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha,
/* Update timers after login */
ddb_entry->default_relogin_timeout =
- le16_to_cpu(fw_ddb_entry->def_timeout);
+ (le16_to_cpu(fw_ddb_entry->def_timeout) > LOGIN_TOV) &&
+ (le16_to_cpu(fw_ddb_entry->def_timeout) < LOGIN_TOV * 10) ?
+ le16_to_cpu(fw_ddb_entry->def_timeout) : LOGIN_TOV;
ddb_entry->default_time2wait =
le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait);
@@ -1970,6 +1973,42 @@ mem_alloc_error_exit:
}
/**
+ * qla4_8xxx_check_temp - Check the ISP82XX temperature.
+ * @ha: adapter block pointer.
+ *
+ * Note: The caller should not hold the idc lock.
+ **/
+static int qla4_8xxx_check_temp(struct scsi_qla_host *ha)
+{
+ uint32_t temp, temp_state, temp_val;
+ int status = QLA_SUCCESS;
+
+ temp = qla4_8xxx_rd_32(ha, CRB_TEMP_STATE);
+
+ temp_state = qla82xx_get_temp_state(temp);
+ temp_val = qla82xx_get_temp_val(temp);
+
+ if (temp_state == QLA82XX_TEMP_PANIC) {
+ ql4_printk(KERN_WARNING, ha, "Device temperature %d degrees C"
+ " exceeds maximum allowed. Hardware has been shut"
+ " down.\n", temp_val);
+ status = QLA_ERROR;
+ } else if (temp_state == QLA82XX_TEMP_WARN) {
+ if (ha->temperature == QLA82XX_TEMP_NORMAL)
+ ql4_printk(KERN_WARNING, ha, "Device temperature %d"
+ " degrees C exceeds operating range."
+ " Immediate action needed.\n", temp_val);
+ } else {
+ if (ha->temperature == QLA82XX_TEMP_WARN)
+ ql4_printk(KERN_INFO, ha, "Device temperature is"
+ " now %d degrees C in normal range.\n",
+ temp_val);
+ }
+ ha->temperature = temp_state;
+ return status;
+}
+
+/**
* qla4_8xxx_check_fw_alive - Check firmware health
* @ha: Pointer to host adapter structure.
*
@@ -2040,7 +2079,16 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha)
test_bit(DPC_RESET_HA, &ha->dpc_flags) ||
test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags))) {
dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
- if (dev_state == QLA82XX_DEV_NEED_RESET &&
+
+ if (qla4_8xxx_check_temp(ha)) {
+ ql4_printk(KERN_INFO, ha, "disabling pause"
+ " transmit on port 0 & 1.\n");
+ qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x98,
+ CRB_NIU_XG_PAUSE_CTL_P0 |
+ CRB_NIU_XG_PAUSE_CTL_P1);
+ set_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags);
+ qla4xxx_wake_dpc(ha);
+ } else if (dev_state == QLA82XX_DEV_NEED_RESET &&
!test_bit(DPC_RESET_HA, &ha->dpc_flags)) {
if (!ql4xdontresethba) {
ql4_printk(KERN_INFO, ha, "%s: HW State: "
@@ -2057,9 +2105,21 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha)
} else {
/* Check firmware health */
if (qla4_8xxx_check_fw_alive(ha)) {
+ ql4_printk(KERN_INFO, ha, "disabling pause"
+ " transmit on port 0 & 1.\n");
+ qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x98,
+ CRB_NIU_XG_PAUSE_CTL_P0 |
+ CRB_NIU_XG_PAUSE_CTL_P1);
halt_status = qla4_8xxx_rd_32(ha,
QLA82XX_PEG_HALT_STATUS1);
+ if (LSW(MSB(halt_status)) == 0x67)
+ ql4_printk(KERN_ERR, ha, "%s:"
+ " Firmware aborted with"
+ " error code 0x00006700."
+ " Device is being reset\n",
+ __func__);
+
/* Since we cannot change dev_state in interrupt
* context, set appropriate DPC flag then wakeup
* DPC */
@@ -2078,7 +2138,7 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha)
}
}
-void qla4xxx_check_relogin_flash_ddb(struct iscsi_cls_session *cls_sess)
+static void qla4xxx_check_relogin_flash_ddb(struct iscsi_cls_session *cls_sess)
{
struct iscsi_session *sess;
struct ddb_entry *ddb_entry;
@@ -3826,16 +3886,14 @@ exit_check:
return ret;
}
-static void qla4xxx_free_nt_list(struct list_head *list_nt)
+static void qla4xxx_free_ddb_list(struct list_head *list_ddb)
{
- struct qla_ddb_index *nt_ddb_idx, *nt_ddb_idx_tmp;
+ struct qla_ddb_index *ddb_idx, *ddb_idx_tmp;
- /* Free up the normaltargets list */
- list_for_each_entry_safe(nt_ddb_idx, nt_ddb_idx_tmp, list_nt, list) {
- list_del_init(&nt_ddb_idx->list);
- vfree(nt_ddb_idx);
+ list_for_each_entry_safe(ddb_idx, ddb_idx_tmp, list_ddb, list) {
+ list_del_init(&ddb_idx->list);
+ vfree(ddb_idx);
}
-
}
static struct iscsi_endpoint *qla4xxx_get_ep_fwdb(struct scsi_qla_host *ha,
@@ -3884,6 +3942,8 @@ static int qla4xxx_verify_boot_idx(struct scsi_qla_host *ha, uint16_t idx)
static void qla4xxx_setup_flash_ddb_entry(struct scsi_qla_host *ha,
struct ddb_entry *ddb_entry)
{
+ uint16_t def_timeout;
+
ddb_entry->ddb_type = FLASH_DDB;
ddb_entry->fw_ddb_index = INVALID_ENTRY;
ddb_entry->fw_ddb_device_state = DDB_DS_NO_CONNECTION_ACTIVE;
@@ -3894,9 +3954,10 @@ static void qla4xxx_setup_flash_ddb_entry(struct scsi_qla_host *ha,
atomic_set(&ddb_entry->retry_relogin_timer, INVALID_ENTRY);
atomic_set(&ddb_entry->relogin_timer, 0);
atomic_set(&ddb_entry->relogin_retry_count, 0);
-
+ def_timeout = le16_to_cpu(ddb_entry->fw_ddb_entry.def_timeout);
ddb_entry->default_relogin_timeout =
- le16_to_cpu(ddb_entry->fw_ddb_entry.def_timeout);
+ (def_timeout > LOGIN_TOV) && (def_timeout < LOGIN_TOV * 10) ?
+ def_timeout : LOGIN_TOV;
ddb_entry->default_time2wait =
le16_to_cpu(ddb_entry->fw_ddb_entry.iscsi_def_time2wait);
}
@@ -3934,7 +3995,6 @@ static void qla4xxx_wait_for_ip_configuration(struct scsi_qla_host *ha)
ip_state == IP_ADDRSTATE_DEPRICATED ||
ip_state == IP_ADDRSTATE_DISABLING)
ip_idx[idx] = -1;
-
}
/* Break if all IP states checked */
@@ -3947,58 +4007,37 @@ static void qla4xxx_wait_for_ip_configuration(struct scsi_qla_host *ha)
} while (time_after(wtime, jiffies));
}
-void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset)
+static void qla4xxx_build_st_list(struct scsi_qla_host *ha,
+ struct list_head *list_st)
{
+ struct qla_ddb_index *st_ddb_idx;
int max_ddbs;
+ int fw_idx_size;
+ struct dev_db_entry *fw_ddb_entry;
+ dma_addr_t fw_ddb_dma;
int ret;
uint32_t idx = 0, next_idx = 0;
uint32_t state = 0, conn_err = 0;
- uint16_t conn_id;
- struct dev_db_entry *fw_ddb_entry;
- struct ddb_entry *ddb_entry = NULL;
- dma_addr_t fw_ddb_dma;
- struct iscsi_cls_session *cls_sess;
- struct iscsi_session *sess;
- struct iscsi_cls_conn *cls_conn;
- struct iscsi_endpoint *ep;
- uint16_t cmds_max = 32, tmo = 0;
- uint32_t initial_cmdsn = 0;
- struct list_head list_st, list_nt; /* List of sendtargets */
- struct qla_ddb_index *st_ddb_idx, *st_ddb_idx_tmp;
- int fw_idx_size;
- unsigned long wtime;
- struct qla_ddb_index *nt_ddb_idx;
-
- if (!test_bit(AF_LINK_UP, &ha->flags)) {
- set_bit(AF_BUILD_DDB_LIST, &ha->flags);
- ha->is_reset = is_reset;
- return;
- }
- max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :
- MAX_DEV_DB_ENTRIES;
+ uint16_t conn_id = 0;
fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL,
&fw_ddb_dma);
if (fw_ddb_entry == NULL) {
DEBUG2(ql4_printk(KERN_ERR, ha, "Out of memory\n"));
- goto exit_ddb_list;
+ goto exit_st_list;
}
- INIT_LIST_HEAD(&list_st);
- INIT_LIST_HEAD(&list_nt);
+ max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :
+ MAX_DEV_DB_ENTRIES;
fw_idx_size = sizeof(struct qla_ddb_index);
for (idx = 0; idx < max_ddbs; idx = next_idx) {
- ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry,
- fw_ddb_dma, NULL,
- &next_idx, &state, &conn_err,
- NULL, &conn_id);
+ ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry, fw_ddb_dma,
+ NULL, &next_idx, &state,
+ &conn_err, NULL, &conn_id);
if (ret == QLA_ERROR)
break;
- if (qla4xxx_verify_boot_idx(ha, idx) != QLA_SUCCESS)
- goto continue_next_st;
-
/* Check if ST, add to the list_st */
if (strlen((char *) fw_ddb_entry->iscsi_name) != 0)
goto continue_next_st;
@@ -4009,59 +4048,155 @@ void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset)
st_ddb_idx->fw_ddb_idx = idx;
- list_add_tail(&st_ddb_idx->list, &list_st);
+ list_add_tail(&st_ddb_idx->list, list_st);
continue_next_st:
if (next_idx == 0)
break;
}
- /* Before issuing conn open mbox, ensure all IPs states are configured
- * Note, conn open fails if IPs are not configured
+exit_st_list:
+ if (fw_ddb_entry)
+ dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma);
+}
+
+/**
+ * qla4xxx_remove_failed_ddb - Remove inactive or failed ddb from list
+ * @ha: pointer to adapter structure
+ * @list_ddb: List from which failed ddb to be removed
+ *
+ * Iterate over the list of DDBs and find and remove DDBs that are either in
+ * no connection active state or failed state
+ **/
+static void qla4xxx_remove_failed_ddb(struct scsi_qla_host *ha,
+ struct list_head *list_ddb)
+{
+ struct qla_ddb_index *ddb_idx, *ddb_idx_tmp;
+ uint32_t next_idx = 0;
+ uint32_t state = 0, conn_err = 0;
+ int ret;
+
+ list_for_each_entry_safe(ddb_idx, ddb_idx_tmp, list_ddb, list) {
+ ret = qla4xxx_get_fwddb_entry(ha, ddb_idx->fw_ddb_idx,
+ NULL, 0, NULL, &next_idx, &state,
+ &conn_err, NULL, NULL);
+ if (ret == QLA_ERROR)
+ continue;
+
+ if (state == DDB_DS_NO_CONNECTION_ACTIVE ||
+ state == DDB_DS_SESSION_FAILED) {
+ list_del_init(&ddb_idx->list);
+ vfree(ddb_idx);
+ }
+ }
+}
+
+static int qla4xxx_sess_conn_setup(struct scsi_qla_host *ha,
+ struct dev_db_entry *fw_ddb_entry,
+ int is_reset)
+{
+ struct iscsi_cls_session *cls_sess;
+ struct iscsi_session *sess;
+ struct iscsi_cls_conn *cls_conn;
+ struct iscsi_endpoint *ep;
+ uint16_t cmds_max = 32;
+ uint16_t conn_id = 0;
+ uint32_t initial_cmdsn = 0;
+ int ret = QLA_SUCCESS;
+
+ struct ddb_entry *ddb_entry = NULL;
+
+ /* Create session object, with INVALID_ENTRY,
+ * the targer_id would get set when we issue the login
*/
- qla4xxx_wait_for_ip_configuration(ha);
+ cls_sess = iscsi_session_setup(&qla4xxx_iscsi_transport, ha->host,
+ cmds_max, sizeof(struct ddb_entry),
+ sizeof(struct ql4_task_data),
+ initial_cmdsn, INVALID_ENTRY);
+ if (!cls_sess) {
+ ret = QLA_ERROR;
+ goto exit_setup;
+ }
- /* Go thru the STs and fire the sendtargets by issuing conn open mbx */
- list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st, list) {
- qla4xxx_conn_open(ha, st_ddb_idx->fw_ddb_idx);
+ /*
+ * so calling module_put function to decrement the
+ * reference count.
+ **/
+ module_put(qla4xxx_iscsi_transport.owner);
+ sess = cls_sess->dd_data;
+ ddb_entry = sess->dd_data;
+ ddb_entry->sess = cls_sess;
+
+ cls_sess->recovery_tmo = ql4xsess_recovery_tmo;
+ memcpy(&ddb_entry->fw_ddb_entry, fw_ddb_entry,
+ sizeof(struct dev_db_entry));
+
+ qla4xxx_setup_flash_ddb_entry(ha, ddb_entry);
+
+ cls_conn = iscsi_conn_setup(cls_sess, sizeof(struct qla_conn), conn_id);
+
+ if (!cls_conn) {
+ ret = QLA_ERROR;
+ goto exit_setup;
}
- /* Wait to ensure all sendtargets are done for min 12 sec wait */
- tmo = ((ha->def_timeout < LOGIN_TOV) ? LOGIN_TOV : ha->def_timeout);
- DEBUG2(ql4_printk(KERN_INFO, ha,
- "Default time to wait for build ddb %d\n", tmo));
+ ddb_entry->conn = cls_conn;
- wtime = jiffies + (HZ * tmo);
- do {
- list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st,
- list) {
- ret = qla4xxx_get_fwddb_entry(ha,
- st_ddb_idx->fw_ddb_idx,
- NULL, 0, NULL, &next_idx,
- &state, &conn_err, NULL,
- NULL);
- if (ret == QLA_ERROR)
- continue;
+ /* Setup ep, for displaying attributes in sysfs */
+ ep = qla4xxx_get_ep_fwdb(ha, fw_ddb_entry);
+ if (ep) {
+ ep->conn = cls_conn;
+ cls_conn->ep = ep;
+ } else {
+ DEBUG2(ql4_printk(KERN_ERR, ha, "Unable to get ep\n"));
+ ret = QLA_ERROR;
+ goto exit_setup;
+ }
- if (state == DDB_DS_NO_CONNECTION_ACTIVE ||
- state == DDB_DS_SESSION_FAILED) {
- list_del_init(&st_ddb_idx->list);
- vfree(st_ddb_idx);
- }
- }
- schedule_timeout_uninterruptible(HZ / 10);
- } while (time_after(wtime, jiffies));
+ /* Update sess/conn params */
+ qla4xxx_copy_fwddb_param(ha, fw_ddb_entry, cls_sess, cls_conn);
- /* Free up the sendtargets list */
- list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st, list) {
- list_del_init(&st_ddb_idx->list);
- vfree(st_ddb_idx);
+ if (is_reset == RESET_ADAPTER) {
+ iscsi_block_session(cls_sess);
+ /* Use the relogin path to discover new devices
+ * by short-circuting the logic of setting
+ * timer to relogin - instead set the flags
+ * to initiate login right away.
+ */
+ set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags);
+ set_bit(DF_RELOGIN, &ddb_entry->flags);
}
+exit_setup:
+ return ret;
+}
+
+static void qla4xxx_build_nt_list(struct scsi_qla_host *ha,
+ struct list_head *list_nt, int is_reset)
+{
+ struct dev_db_entry *fw_ddb_entry;
+ dma_addr_t fw_ddb_dma;
+ int max_ddbs;
+ int fw_idx_size;
+ int ret;
+ uint32_t idx = 0, next_idx = 0;
+ uint32_t state = 0, conn_err = 0;
+ uint16_t conn_id = 0;
+ struct qla_ddb_index *nt_ddb_idx;
+
+ fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL,
+ &fw_ddb_dma);
+ if (fw_ddb_entry == NULL) {
+ DEBUG2(ql4_printk(KERN_ERR, ha, "Out of memory\n"));
+ goto exit_nt_list;
+ }
+ max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :
+ MAX_DEV_DB_ENTRIES;
+ fw_idx_size = sizeof(struct qla_ddb_index);
+
for (idx = 0; idx < max_ddbs; idx = next_idx) {
- ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry,
- fw_ddb_dma, NULL,
- &next_idx, &state, &conn_err,
- NULL, &conn_id);
+ ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry, fw_ddb_dma,
+ NULL, &next_idx, &state,
+ &conn_err, NULL, &conn_id);
if (ret == QLA_ERROR)
break;
@@ -4072,107 +4207,113 @@ continue_next_st:
if (strlen((char *) fw_ddb_entry->iscsi_name) == 0)
goto continue_next_nt;
- if (state == DDB_DS_NO_CONNECTION_ACTIVE ||
- state == DDB_DS_SESSION_FAILED) {
- DEBUG2(ql4_printk(KERN_INFO, ha,
- "Adding DDB to session = 0x%x\n",
- idx));
- if (is_reset == INIT_ADAPTER) {
- nt_ddb_idx = vmalloc(fw_idx_size);
- if (!nt_ddb_idx)
- break;
-
- nt_ddb_idx->fw_ddb_idx = idx;
-
- memcpy(&nt_ddb_idx->fw_ddb, fw_ddb_entry,
- sizeof(struct dev_db_entry));
-
- if (qla4xxx_is_flash_ddb_exists(ha, &list_nt,
- fw_ddb_entry) == QLA_SUCCESS) {
- vfree(nt_ddb_idx);
- goto continue_next_nt;
- }
- list_add_tail(&nt_ddb_idx->list, &list_nt);
- } else if (is_reset == RESET_ADAPTER) {
- if (qla4xxx_is_session_exists(ha,
- fw_ddb_entry) == QLA_SUCCESS)
- goto continue_next_nt;
- }
+ if (!(state == DDB_DS_NO_CONNECTION_ACTIVE ||
+ state == DDB_DS_SESSION_FAILED))
+ goto continue_next_nt;
- /* Create session object, with INVALID_ENTRY,
- * the targer_id would get set when we issue the login
- */
- cls_sess = iscsi_session_setup(&qla4xxx_iscsi_transport,
- ha->host, cmds_max,
- sizeof(struct ddb_entry),
- sizeof(struct ql4_task_data),
- initial_cmdsn, INVALID_ENTRY);
- if (!cls_sess)
- goto exit_ddb_list;
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "Adding DDB to session = 0x%x\n", idx));
+ if (is_reset == INIT_ADAPTER) {
+ nt_ddb_idx = vmalloc(fw_idx_size);
+ if (!nt_ddb_idx)
+ break;
- /*
- * iscsi_session_setup increments the driver reference
- * count which wouldn't let the driver to be unloaded.
- * so calling module_put function to decrement the
- * reference count.
- **/
- module_put(qla4xxx_iscsi_transport.owner);
- sess = cls_sess->dd_data;
- ddb_entry = sess->dd_data;
- ddb_entry->sess = cls_sess;
+ nt_ddb_idx->fw_ddb_idx = idx;
- cls_sess->recovery_tmo = ql4xsess_recovery_tmo;
- memcpy(&ddb_entry->fw_ddb_entry, fw_ddb_entry,
+ memcpy(&nt_ddb_idx->fw_ddb, fw_ddb_entry,
sizeof(struct dev_db_entry));
- qla4xxx_setup_flash_ddb_entry(ha, ddb_entry);
-
- cls_conn = iscsi_conn_setup(cls_sess,
- sizeof(struct qla_conn),
- conn_id);
- if (!cls_conn)
- goto exit_ddb_list;
-
- ddb_entry->conn = cls_conn;
-
- /* Setup ep, for displaying attributes in sysfs */
- ep = qla4xxx_get_ep_fwdb(ha, fw_ddb_entry);
- if (ep) {
- ep->conn = cls_conn;
- cls_conn->ep = ep;
- } else {
- DEBUG2(ql4_printk(KERN_ERR, ha,
- "Unable to get ep\n"));
- }
-
- /* Update sess/conn params */
- qla4xxx_copy_fwddb_param(ha, fw_ddb_entry, cls_sess,
- cls_conn);
-
- if (is_reset == RESET_ADAPTER) {
- iscsi_block_session(cls_sess);
- /* Use the relogin path to discover new devices
- * by short-circuting the logic of setting
- * timer to relogin - instead set the flags
- * to initiate login right away.
- */
- set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags);
- set_bit(DF_RELOGIN, &ddb_entry->flags);
+ if (qla4xxx_is_flash_ddb_exists(ha, list_nt,
+ fw_ddb_entry) == QLA_SUCCESS) {
+ vfree(nt_ddb_idx);
+ goto continue_next_nt;
}
+ list_add_tail(&nt_ddb_idx->list, list_nt);
+ } else if (is_reset == RESET_ADAPTER) {
+ if (qla4xxx_is_session_exists(ha, fw_ddb_entry) ==
+ QLA_SUCCESS)
+ goto continue_next_nt;
}
+
+ ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, is_reset);
+ if (ret == QLA_ERROR)
+ goto exit_nt_list;
+
continue_next_nt:
if (next_idx == 0)
break;
}
-exit_ddb_list:
- qla4xxx_free_nt_list(&list_nt);
+
+exit_nt_list:
if (fw_ddb_entry)
dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma);
+}
+
+/**
+ * qla4xxx_build_ddb_list - Build ddb list and setup sessions
+ * @ha: pointer to adapter structure
+ * @is_reset: Is this init path or reset path
+ *
+ * Create a list of sendtargets (st) from firmware DDBs, issue send targets
+ * using connection open, then create the list of normal targets (nt)
+ * from firmware DDBs. Based on the list of nt setup session and connection
+ * objects.
+ **/
+void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset)
+{
+ uint16_t tmo = 0;
+ struct list_head list_st, list_nt;
+ struct qla_ddb_index *st_ddb_idx, *st_ddb_idx_tmp;
+ unsigned long wtime;
+
+ if (!test_bit(AF_LINK_UP, &ha->flags)) {
+ set_bit(AF_BUILD_DDB_LIST, &ha->flags);
+ ha->is_reset = is_reset;
+ return;
+ }
+
+ INIT_LIST_HEAD(&list_st);
+ INIT_LIST_HEAD(&list_nt);
+
+ qla4xxx_build_st_list(ha, &list_st);
+
+ /* Before issuing conn open mbox, ensure all IPs states are configured
+ * Note, conn open fails if IPs are not configured
+ */
+ qla4xxx_wait_for_ip_configuration(ha);
+
+ /* Go thru the STs and fire the sendtargets by issuing conn open mbx */
+ list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st, list) {
+ qla4xxx_conn_open(ha, st_ddb_idx->fw_ddb_idx);
+ }
+
+ /* Wait to ensure all sendtargets are done for min 12 sec wait */
+ tmo = ((ha->def_timeout > LOGIN_TOV) &&
+ (ha->def_timeout < LOGIN_TOV * 10) ?
+ ha->def_timeout : LOGIN_TOV);
+
+ DEBUG2(ql4_printk(KERN_INFO, ha,
+ "Default time to wait for build ddb %d\n", tmo));
+
+ wtime = jiffies + (HZ * tmo);
+ do {
+ if (list_empty(&list_st))
+ break;
+
+ qla4xxx_remove_failed_ddb(ha, &list_st);
+ schedule_timeout_uninterruptible(HZ / 10);
+ } while (time_after(wtime, jiffies));
+
+ /* Free up the sendtargets list */
+ qla4xxx_free_ddb_list(&list_st);
+
+ qla4xxx_build_nt_list(ha, &list_nt, is_reset);
+
+ qla4xxx_free_ddb_list(&list_nt);
qla4xxx_free_ddb_index(ha);
}
-
/**
* qla4xxx_probe_adapter - callback function to probe HBA
* @pdev: pointer to pci_dev structure
diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h
index 26a3fa34a33c..133989b3a9f4 100644
--- a/drivers/scsi/qla4xxx/ql4_version.h
+++ b/drivers/scsi/qla4xxx/ql4_version.h
@@ -5,4 +5,4 @@
* See LICENSE.qla4xxx for copyright and licensing details.
*/
-#define QLA4XXX_DRIVER_VERSION "5.02.00-k10"
+#define QLA4XXX_DRIVER_VERSION "5.02.00-k12"
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index f85cfa6c47b5..b2c95dbe9d65 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1316,15 +1316,10 @@ static inline int scsi_target_queue_ready(struct Scsi_Host *shost,
}
if (scsi_target_is_busy(starget)) {
- if (list_empty(&sdev->starved_entry))
- list_add_tail(&sdev->starved_entry,
- &shost->starved_list);
+ list_move_tail(&sdev->starved_entry, &shost->starved_list);
return 0;
}
- /* We're OK to process the command, so we can't be starved */
- if (!list_empty(&sdev->starved_entry))
- list_del_init(&sdev->starved_entry);
return 1;
}
diff --git a/drivers/scsi/scsi_netlink.c b/drivers/scsi/scsi_netlink.c
index 44f76e8b58af..c77628afbf9f 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 b3c6d957fbd8..89da43f73c00 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/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 1b214910b714..f59d4a05ecd7 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -3048,7 +3048,8 @@ fc_remote_port_rolechg(struct fc_rport *rport, u32 roles)
spin_lock_irqsave(shost->host_lock, flags);
rport->flags &= ~(FC_RPORT_FAST_FAIL_TIMEDOUT |
- FC_RPORT_DEVLOSS_PENDING);
+ FC_RPORT_DEVLOSS_PENDING |
+ FC_RPORT_DEVLOSS_CALLBK_DONE);
spin_unlock_irqrestore(shost->host_lock, flags);
/* ensure any stgt delete functions are done */
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 7b3f8075e2a5..c691fb50e6cb 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/scsi/sg.c b/drivers/scsi/sg.c
index 02d99982a74d..eacd46bb36b9 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -2368,16 +2368,15 @@ static ssize_t
sg_proc_write_adio(struct file *filp, const char __user *buffer,
size_t count, loff_t *off)
{
- int num;
- char buff[11];
+ int err;
+ unsigned long num;
if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
return -EACCES;
- num = (count < 10) ? count : 10;
- if (copy_from_user(buff, buffer, num))
- return -EFAULT;
- buff[num] = '\0';
- sg_allow_dio = simple_strtoul(buff, NULL, 10) ? 1 : 0;
+ err = kstrtoul_from_user(buffer, count, 0, &num);
+ if (err)
+ return err;
+ sg_allow_dio = num ? 1 : 0;
return count;
}
@@ -2390,17 +2389,15 @@ static ssize_t
sg_proc_write_dressz(struct file *filp, const char __user *buffer,
size_t count, loff_t *off)
{
- int num;
+ int err;
unsigned long k = ULONG_MAX;
- char buff[11];
if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
return -EACCES;
- num = (count < 10) ? count : 10;
- if (copy_from_user(buff, buffer, num))
- return -EFAULT;
- buff[num] = '\0';
- k = simple_strtoul(buff, NULL, 10);
+
+ err = kstrtoul_from_user(buffer, count, 0, &k);
+ if (err)
+ return err;
if (k <= 1048576) { /* limit "big buff" to 1 MB */
sg_big_buff = k;
return count;
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index b4543f575f46..36d1ed7817eb 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -839,6 +839,10 @@ static void sym53c8xx_slave_destroy(struct scsi_device *sdev)
struct sym_lcb *lp = sym_lp(tp, sdev->lun);
unsigned long flags;
+ /* if slave_alloc returned before allocating a sym_lcb, return */
+ if (!lp)
+ return;
+
spin_lock_irqsave(np->s.host->host_lock, flags);
if (lp->busy_itlq || lp->busy_itl) {
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 56abf55e49da..3f9a47ec67dc 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 e743a45ee92c..8418eb036651 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 0a282e5fcc9c..d46e55c720b7 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 f1f5efbc3404..2f9cb43a2398 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 7086583b9107..2a6429d8c363 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/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c
index 520e8286db28..49d209173f55 100644
--- a/drivers/ssb/driver_pcicore.c
+++ b/drivers/ssb/driver_pcicore.c
@@ -75,7 +75,7 @@ static u32 get_cfgspace_addr(struct ssb_pcicore *pc,
u32 tmp;
/* We do only have one cardbus device behind the bridge. */
- if (pc->cardbusmode && (dev >= 1))
+ if (pc->cardbusmode && (dev > 1))
goto out;
if (bus == 0) {
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index 0d18d80bcd25..9bcf87ae4c00 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 da4b4f5553f5..006cf14c577a 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 5865029db0f6..28aba00dc629 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 e7dbb6f814d5..1bca43e847c7 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 828526d4c289..aae0505a36c4 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 fd33f5a12dcc..957f0ed0d81a 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 3550f905367e..bdc5a38cddf7 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 c019df933cc9..43ebc43e6b9a 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 27e5347e2e19..bd21f0554392 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 264be2dbd2a4..d775be0173ea 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 fb1fc41dcd79..fc2884ab02a2 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 0dcba8065780..262bb94ad27e 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 01a716380e0a..4ea249e7adab 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 ec6f69fcf399..d2a4bce89623 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 045c70683193..6d000f60fb0e 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 4f01a76e9829..62b9795ee424 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 3dedb3c1420a..fde8140ae88b 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 04e93c49f03a..280c84ec4cc2 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 7b256a948c27..a007e7442be8 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 c99addfb6242..9413b37490c2 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 0385735ac6df..0380babed22c 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 a45c0b507067..8ff5f38ea196 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 70f59b13c34d..3f5f5b3e5a35 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 b22bb39b5f69..8c8bcae8ded8 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 b7175fe1b15f..70e006b50f29 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 deac938d8505..d071c838ac2a 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 c5a0d27a02dc..4d20e9f74118 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 6cd4cd67a1dd..7a2501776679 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 f68218012f23..5f7f8cd3a661 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 792aac0a8e7b..dd2bca7b56fa 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 8a060a8a7224..8dd8897ad860 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 6903d3992eca..c94382b917ac 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 0302d82a12f7..76ea4a8f2c75 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 72816cf16704..337e38c3a0f0 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 50defec318cc..50defec318cc 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 bee7280bbed9..f8f0da952288 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 fc850bac88c1..9012dee0c348 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 3c74d826e2e6..000000000000
--- 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 91415a85e8d2..000000000000
--- 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 e9809d375162..000000000000
--- 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 614653b686a0..000000000000
--- 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 078a520481cf..000000000000
--- 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 abbf42d05e5a..000000000000
--- 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 a6939fc8ba18..000000000000
--- 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 bf5546b90110..000000000000
--- 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 ad44b8bd8057..000000000000
--- 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 1f04f9658736..000000000000
--- 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 946a43a73fd7..000000000000
--- 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 57d35dc63ddb..000000000000
--- 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 b465bec43553..000000000000
--- 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 c239e5f4ab9a..000000000000
--- 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 5ff8c93198de..000000000000
--- 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 55a571a69529..000000000000
--- 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 e646a6ccce75..000000000000
--- 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 7388a1e72b38..000000000000
--- 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 908e7b08c214..000000000000
--- 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 aa2d5d7fee2b..000000000000
--- 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 ea2652604a57..000000000000
--- 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 6214e3b6d975..000000000000
--- 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 19b48d60857f..000000000000
--- 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 8ba6c832471e..000000000000
--- 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 69bac036d10e..000000000000
--- 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 131182bf5abb..000000000000
--- 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 6a6e52fc22c1..000000000000
--- 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 a11e6769e234..000000000000
--- 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 4b4db2f93cd4..000000000000
--- 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 e9c5c836ceff..000000000000
--- 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 51916f3cc40c..000000000000
--- 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 a3337e382ee9..000000000000
--- 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 df50048cfbc0..000000000000
--- 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 115a552c5c7f..000000000000
--- 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 d88ab8d8e37d..000000000000
--- 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 62ffe78a8c81..000000000000
--- 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 d45952df5f5b..000000000000
--- 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 55d120fe8aed..000000000000
--- 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 5a369100ca68..000000000000
--- 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 78dbce8f2c5e..000000000000
--- 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 50e779cf1ad8..000000000000
--- 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 50a2c9bd5a55..000000000000
--- 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 de3412aada5d..000000000000
--- 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 999aefe3274c..000000000000
--- 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 96b70cfd6245..000000000000
--- 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 9ae45fcbe3e3..000000000000
--- 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 82794d920cec..000000000000
--- 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 e814648953a5..000000000000
--- 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 b16940e32c83..000000000000
--- 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 d82b366c279f..000000000000
--- 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 4f209b62cae1..000000000000
--- 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 653610953d28..000000000000
--- 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 6a2cd50a17df..bdaec8d2ca0c 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 f18e3e140413..63800ba71d06 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 635bb86cdcff..78b6cb743769 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 c3d73f8431ae..d8f5f694ec35 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 8b307b428791..400df8cbee53 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 a0743b85d54e..9240c85ce241 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 5e148b512c97..d3e82430eba6 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 d0e2d514968a..af8d62818f13 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 2542c3743904..56d74dc2fbd5 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 861a4b3fe857..419f8c34ecdf 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 076f86675ce6..9112cd882154 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 02fafecd4773..897a3a99c794 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 c44e41af2880..1c5780f1571b 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 412b87947f66..e66579e6147a 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 c241074a4b5e..2222d6919ef5 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 08a449b4abf9..f50582169b24 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/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index 8599545cdf9e..ac44af165b27 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -27,8 +27,7 @@
#include <scsi/scsi_device.h>
#include <scsi/iscsi_proto.h>
#include <target/target_core_base.h>
-#include <target/target_core_tmr.h>
-#include <target/target_core_transport.h>
+#include <target/target_core_fabric.h>
#include "iscsi_target_core.h"
#include "iscsi_target_parameters.h"
@@ -284,8 +283,8 @@ static struct iscsi_np *iscsit_get_np(
sock_in6 = (struct sockaddr_in6 *)sockaddr;
sock_in6_e = (struct sockaddr_in6 *)&np->np_sockaddr;
- if (!memcmp((void *)&sock_in6->sin6_addr.in6_u,
- (void *)&sock_in6_e->sin6_addr.in6_u,
+ if (!memcmp(&sock_in6->sin6_addr.in6_u,
+ &sock_in6_e->sin6_addr.in6_u,
sizeof(struct in6_addr)))
ip_match = 1;
@@ -1225,7 +1224,7 @@ static void iscsit_do_crypto_hash_buf(
crypto_hash_init(hash);
- sg_init_one(&sg, (u8 *)buf, payload_length);
+ sg_init_one(&sg, buf, payload_length);
crypto_hash_update(hash, &sg, payload_length);
if (padding) {
@@ -1603,7 +1602,7 @@ static int iscsit_handle_nop_out(
/*
* Attach ping data to struct iscsi_cmd->buf_ptr.
*/
- cmd->buf_ptr = (void *)ping_data;
+ cmd->buf_ptr = ping_data;
cmd->buf_ptr_size = payload_length;
pr_debug("Got %u bytes of NOPOUT ping"
@@ -3197,7 +3196,7 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
end_of_buf = 1;
goto eob;
}
- memcpy((void *)payload + payload_len, buf, len);
+ memcpy(payload + payload_len, buf, len);
payload_len += len;
spin_lock(&tiqn->tiqn_tpg_lock);
@@ -3229,7 +3228,7 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
end_of_buf = 1;
goto eob;
}
- memcpy((void *)payload + payload_len, buf, len);
+ memcpy(payload + payload_len, buf, len);
payload_len += len;
}
spin_unlock(&tpg->tpg_np_lock);
@@ -3486,7 +3485,7 @@ int iscsi_target_tx_thread(void *arg)
struct iscsi_conn *conn;
struct iscsi_queue_req *qr = NULL;
struct se_cmd *se_cmd;
- struct iscsi_thread_set *ts = (struct iscsi_thread_set *)arg;
+ struct iscsi_thread_set *ts = arg;
/*
* Allow ourselves to be interrupted by SIGINT so that a
* connection recovery / failure event can be triggered externally.
@@ -3775,7 +3774,7 @@ int iscsi_target_rx_thread(void *arg)
u8 buffer[ISCSI_HDR_LEN], opcode;
u32 checksum = 0, digest = 0;
struct iscsi_conn *conn = NULL;
- struct iscsi_thread_set *ts = (struct iscsi_thread_set *)arg;
+ struct iscsi_thread_set *ts = arg;
struct kvec iov;
/*
* Allow ourselves to be interrupted by SIGINT so that a
diff --git a/drivers/target/iscsi/iscsi_target_auth.c b/drivers/target/iscsi/iscsi_target_auth.c
index 1cd6ce373b83..db0cf7c8adde 100644
--- a/drivers/target/iscsi/iscsi_target_auth.c
+++ b/drivers/target/iscsi/iscsi_target_auth.c
@@ -82,7 +82,7 @@ static void chap_gen_challenge(
unsigned int *c_len)
{
unsigned char challenge_asciihex[CHAP_CHALLENGE_LENGTH * 2 + 1];
- struct iscsi_chap *chap = (struct iscsi_chap *) conn->auth_protocol;
+ struct iscsi_chap *chap = conn->auth_protocol;
memset(challenge_asciihex, 0, CHAP_CHALLENGE_LENGTH * 2 + 1);
@@ -120,7 +120,7 @@ static struct iscsi_chap *chap_server_open(
if (!conn->auth_protocol)
return NULL;
- chap = (struct iscsi_chap *) conn->auth_protocol;
+ chap = conn->auth_protocol;
/*
* We only support MD5 MDA presently.
*/
@@ -165,14 +165,15 @@ static int chap_server_compute_md5(
unsigned int *nr_out_len)
{
char *endptr;
- unsigned char id, digest[MD5_SIGNATURE_SIZE];
+ unsigned long id;
+ unsigned char digest[MD5_SIGNATURE_SIZE];
unsigned char type, response[MD5_SIGNATURE_SIZE * 2 + 2];
unsigned char identifier[10], *challenge = NULL;
unsigned char *challenge_binhex = NULL;
unsigned char client_digest[MD5_SIGNATURE_SIZE];
unsigned char server_digest[MD5_SIGNATURE_SIZE];
unsigned char chap_n[MAX_CHAP_N_SIZE], chap_r[MAX_RESPONSE_LENGTH];
- struct iscsi_chap *chap = (struct iscsi_chap *) conn->auth_protocol;
+ struct iscsi_chap *chap = conn->auth_protocol;
struct crypto_hash *tfm;
struct hash_desc desc;
struct scatterlist sg;
@@ -246,7 +247,7 @@ static int chap_server_compute_md5(
goto out;
}
- sg_init_one(&sg, (void *)&chap->id, 1);
+ sg_init_one(&sg, &chap->id, 1);
ret = crypto_hash_update(&desc, &sg, 1);
if (ret < 0) {
pr_err("crypto_hash_update() failed for id\n");
@@ -254,7 +255,7 @@ static int chap_server_compute_md5(
goto out;
}
- sg_init_one(&sg, (void *)&auth->password, strlen(auth->password));
+ sg_init_one(&sg, &auth->password, strlen(auth->password));
ret = crypto_hash_update(&desc, &sg, strlen(auth->password));
if (ret < 0) {
pr_err("crypto_hash_update() failed for password\n");
@@ -262,7 +263,7 @@ static int chap_server_compute_md5(
goto out;
}
- sg_init_one(&sg, (void *)chap->challenge, CHAP_CHALLENGE_LENGTH);
+ sg_init_one(&sg, chap->challenge, CHAP_CHALLENGE_LENGTH);
ret = crypto_hash_update(&desc, &sg, CHAP_CHALLENGE_LENGTH);
if (ret < 0) {
pr_err("crypto_hash_update() failed for challenge\n");
@@ -305,14 +306,17 @@ static int chap_server_compute_md5(
}
if (type == HEX)
- id = (unsigned char)simple_strtoul((char *)&identifier[2],
- &endptr, 0);
+ id = simple_strtoul(&identifier[2], &endptr, 0);
else
- id = (unsigned char)simple_strtoul(identifier, &endptr, 0);
+ id = simple_strtoul(identifier, &endptr, 0);
+ if (id > 255) {
+ pr_err("chap identifier: %lu greater than 255\n", id);
+ goto out;
+ }
/*
* RFC 1994 says Identifier is no more than octet (8 bits).
*/
- pr_debug("[server] Got CHAP_I=%d\n", id);
+ pr_debug("[server] Got CHAP_I=%lu\n", id);
/*
* Get CHAP_C.
*/
@@ -351,7 +355,7 @@ static int chap_server_compute_md5(
goto out;
}
- sg_init_one(&sg, (void *)&id, 1);
+ sg_init_one(&sg, &id, 1);
ret = crypto_hash_update(&desc, &sg, 1);
if (ret < 0) {
pr_err("crypto_hash_update() failed for id\n");
@@ -359,7 +363,7 @@ static int chap_server_compute_md5(
goto out;
}
- sg_init_one(&sg, (void *)auth->password_mutual,
+ sg_init_one(&sg, auth->password_mutual,
strlen(auth->password_mutual));
ret = crypto_hash_update(&desc, &sg, strlen(auth->password_mutual));
if (ret < 0) {
@@ -371,7 +375,7 @@ static int chap_server_compute_md5(
/*
* Convert received challenge to binary hex.
*/
- sg_init_one(&sg, (void *)challenge_binhex, challenge_len);
+ sg_init_one(&sg, challenge_binhex, challenge_len);
ret = crypto_hash_update(&desc, &sg, challenge_len);
if (ret < 0) {
pr_err("crypto_hash_update() failed for ma challenge\n");
@@ -414,7 +418,7 @@ static int chap_got_response(
char *nr_out_ptr,
unsigned int *nr_out_len)
{
- struct iscsi_chap *chap = (struct iscsi_chap *) conn->auth_protocol;
+ struct iscsi_chap *chap = conn->auth_protocol;
switch (chap->digest_type) {
case CHAP_DIGEST_MD5:
@@ -437,7 +441,7 @@ u32 chap_main_loop(
int *in_len,
int *out_len)
{
- struct iscsi_chap *chap = (struct iscsi_chap *) conn->auth_protocol;
+ struct iscsi_chap *chap = conn->auth_protocol;
if (!chap) {
chap = chap_server_open(conn, auth, in_text, out_text, out_len);
diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c
index db327845e46b..3468caab47a2 100644
--- a/drivers/target/iscsi/iscsi_target_configfs.c
+++ b/drivers/target/iscsi/iscsi_target_configfs.c
@@ -22,12 +22,8 @@
#include <linux/configfs.h>
#include <linux/export.h>
#include <target/target_core_base.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_fabric.h>
#include <target/target_core_fabric_configfs.h>
-#include <target/target_core_fabric_lib.h>
-#include <target/target_core_device.h>
-#include <target/target_core_tpg.h>
#include <target/target_core_configfs.h>
#include <target/configfs_macros.h>
@@ -56,8 +52,7 @@ struct iscsi_portal_group *lio_get_tpg_from_tpg_item(
{
struct se_portal_group *se_tpg = container_of(to_config_group(item),
struct se_portal_group, tpg_group);
- struct iscsi_portal_group *tpg =
- (struct iscsi_portal_group *)se_tpg->se_tpg_fabric_ptr;
+ struct iscsi_portal_group *tpg = se_tpg->se_tpg_fabric_ptr;
int ret;
if (!tpg) {
@@ -1225,7 +1220,7 @@ struct se_portal_group *lio_target_tiqn_addtpg(
ret = core_tpg_register(
&lio_target_fabric_configfs->tf_ops,
- wwn, &tpg->tpg_se_tpg, (void *)tpg,
+ wwn, &tpg->tpg_se_tpg, tpg,
TRANSPORT_TPG_TYPE_NORMAL);
if (ret < 0)
return NULL;
diff --git a/drivers/target/iscsi/iscsi_target_device.c b/drivers/target/iscsi/iscsi_target_device.c
index a19fa5eea88e..f63ea35bc4ae 100644
--- a/drivers/target/iscsi/iscsi_target_device.c
+++ b/drivers/target/iscsi/iscsi_target_device.c
@@ -21,8 +21,7 @@
#include <scsi/scsi_device.h>
#include <target/target_core_base.h>
-#include <target/target_core_device.h>
-#include <target/target_core_transport.h>
+#include <target/target_core_fabric.h>
#include "iscsi_target_core.h"
#include "iscsi_target_device.h"
diff --git a/drivers/target/iscsi/iscsi_target_erl0.c b/drivers/target/iscsi/iscsi_target_erl0.c
index b7ffc3cd40cc..478451167b62 100644
--- a/drivers/target/iscsi/iscsi_target_erl0.c
+++ b/drivers/target/iscsi/iscsi_target_erl0.c
@@ -21,7 +21,7 @@
#include <scsi/iscsi_proto.h>
#include <target/target_core_base.h>
-#include <target/target_core_transport.h>
+#include <target/target_core_fabric.h>
#include "iscsi_target_core.h"
#include "iscsi_target_seq_pdu_list.h"
diff --git a/drivers/target/iscsi/iscsi_target_erl1.c b/drivers/target/iscsi/iscsi_target_erl1.c
index 101b1beb3bca..255c0d67e898 100644
--- a/drivers/target/iscsi/iscsi_target_erl1.c
+++ b/drivers/target/iscsi/iscsi_target_erl1.c
@@ -21,7 +21,7 @@
#include <linux/list.h>
#include <scsi/iscsi_proto.h>
#include <target/target_core_base.h>
-#include <target/target_core_transport.h>
+#include <target/target_core_fabric.h>
#include "iscsi_target_core.h"
#include "iscsi_target_seq_pdu_list.h"
diff --git a/drivers/target/iscsi/iscsi_target_erl2.c b/drivers/target/iscsi/iscsi_target_erl2.c
index 0b8404c30125..1af1f21af21f 100644
--- a/drivers/target/iscsi/iscsi_target_erl2.c
+++ b/drivers/target/iscsi/iscsi_target_erl2.c
@@ -21,7 +21,7 @@
#include <scsi/iscsi_proto.h>
#include <target/target_core_base.h>
-#include <target/target_core_transport.h>
+#include <target/target_core_fabric.h>
#include "iscsi_target_core.h"
#include "iscsi_target_datain_values.h"
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c
index d734bdec24f9..373b0cc6abd8 100644
--- a/drivers/target/iscsi/iscsi_target_login.c
+++ b/drivers/target/iscsi/iscsi_target_login.c
@@ -23,7 +23,7 @@
#include <linux/crypto.h>
#include <scsi/iscsi_proto.h>
#include <target/target_core_base.h>
-#include <target/target_core_transport.h>
+#include <target/target_core_fabric.h>
#include "iscsi_target_core.h"
#include "iscsi_target_tq.h"
@@ -143,7 +143,7 @@ int iscsi_check_for_session_reinstatement(struct iscsi_conn *conn)
list_for_each_entry_safe(se_sess, se_sess_tmp, &se_tpg->tpg_sess_list,
sess_list) {
- sess_p = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+ sess_p = se_sess->fabric_sess_ptr;
spin_lock(&sess_p->conn_lock);
if (atomic_read(&sess_p->session_fall_back_to_erl0) ||
atomic_read(&sess_p->session_logout) ||
@@ -151,9 +151,9 @@ int iscsi_check_for_session_reinstatement(struct iscsi_conn *conn)
spin_unlock(&sess_p->conn_lock);
continue;
}
- if (!memcmp((void *)sess_p->isid, (void *)conn->sess->isid, 6) &&
- (!strcmp((void *)sess_p->sess_ops->InitiatorName,
- (void *)initiatorname_param->value) &&
+ if (!memcmp(sess_p->isid, conn->sess->isid, 6) &&
+ (!strcmp(sess_p->sess_ops->InitiatorName,
+ initiatorname_param->value) &&
(sess_p->sess_ops->SessionType == sessiontype))) {
atomic_set(&sess_p->session_reinstatement, 1);
spin_unlock(&sess_p->conn_lock);
@@ -229,7 +229,7 @@ static int iscsi_login_zero_tsih_s1(
iscsi_login_set_conn_values(sess, conn, pdu->cid);
sess->init_task_tag = pdu->itt;
- memcpy((void *)&sess->isid, (void *)pdu->isid, 6);
+ memcpy(&sess->isid, pdu->isid, 6);
sess->exp_cmd_sn = pdu->cmdsn;
INIT_LIST_HEAD(&sess->sess_conn_list);
INIT_LIST_HEAD(&sess->sess_ooo_cmdsn_list);
@@ -440,8 +440,7 @@ static int iscsi_login_non_zero_tsih_s2(
atomic_read(&sess_p->session_logout) ||
(sess_p->time2retain_timer_flags & ISCSI_TF_EXPIRED))
continue;
- if (!memcmp((const void *)sess_p->isid,
- (const void *)pdu->isid, 6) &&
+ if (!memcmp(sess_p->isid, pdu->isid, 6) &&
(sess_p->tsih == pdu->tsih)) {
iscsit_inc_session_usage_count(sess_p);
iscsit_stop_time2retain_timer(sess_p);
@@ -654,7 +653,7 @@ static int iscsi_post_login_handler(
spin_lock_bh(&se_tpg->session_lock);
__transport_register_session(&sess->tpg->tpg_se_tpg,
- se_sess->se_node_acl, se_sess, (void *)sess);
+ se_sess->se_node_acl, se_sess, sess);
pr_debug("Moving to TARG_SESS_STATE_LOGGED_IN.\n");
sess->session_state = TARG_SESS_STATE_LOGGED_IN;
@@ -811,7 +810,7 @@ int iscsi_target_setup_login_socket(
* Setup the np->np_sockaddr from the passed sockaddr setup
* in iscsi_target_configfs.c code..
*/
- memcpy((void *)&np->np_sockaddr, (void *)sockaddr,
+ memcpy(&np->np_sockaddr, sockaddr,
sizeof(struct __kernel_sockaddr_storage));
if (sockaddr->ss_family == AF_INET6)
@@ -821,6 +820,7 @@ int iscsi_target_setup_login_socket(
/*
* Set SO_REUSEADDR, and disable Nagel Algorithm with TCP_NODELAY.
*/
+ /* FIXME: Someone please explain why this is endian-safe */
opt = 1;
if (np->np_network_transport == ISCSI_TCP) {
ret = kernel_setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
@@ -832,6 +832,7 @@ int iscsi_target_setup_login_socket(
}
}
+ /* FIXME: Someone please explain why this is endian-safe */
ret = kernel_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
(char *)&opt, sizeof(opt));
if (ret < 0) {
@@ -1206,7 +1207,7 @@ out:
int iscsi_target_login_thread(void *arg)
{
- struct iscsi_np *np = (struct iscsi_np *)arg;
+ struct iscsi_np *np = arg;
int ret;
allow_signal(SIGINT);
diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c
index 98936cb7c294..e89fa7457254 100644
--- a/drivers/target/iscsi/iscsi_target_nego.c
+++ b/drivers/target/iscsi/iscsi_target_nego.c
@@ -21,7 +21,7 @@
#include <linux/ctype.h>
#include <scsi/iscsi_proto.h>
#include <target/target_core_base.h>
-#include <target/target_core_tpg.h>
+#include <target/target_core_fabric.h>
#include "iscsi_target_core.h"
#include "iscsi_target_parameters.h"
@@ -732,7 +732,7 @@ static void iscsi_initiatorname_tolower(
u32 iqn_size = strlen(param_buf), i;
for (i = 0; i < iqn_size; i++) {
- c = (char *)&param_buf[i];
+ c = &param_buf[i];
if (!isupper(*c))
continue;
diff --git a/drivers/target/iscsi/iscsi_target_nodeattrib.c b/drivers/target/iscsi/iscsi_target_nodeattrib.c
index aeafbe0cd7d1..b3c699c4fe8c 100644
--- a/drivers/target/iscsi/iscsi_target_nodeattrib.c
+++ b/drivers/target/iscsi/iscsi_target_nodeattrib.c
@@ -19,7 +19,6 @@
******************************************************************************/
#include <target/target_core_base.h>
-#include <target/target_core_transport.h>
#include "iscsi_target_core.h"
#include "iscsi_target_device.h"
@@ -135,7 +134,7 @@ extern int iscsit_na_nopin_timeout(
spin_lock_bh(&se_nacl->nacl_sess_lock);
se_sess = se_nacl->nacl_sess;
if (se_sess) {
- sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+ sess = se_sess->fabric_sess_ptr;
spin_lock(&sess->conn_lock);
list_for_each_entry(conn, &sess->sess_conn_list,
diff --git a/drivers/target/iscsi/iscsi_target_stat.c b/drivers/target/iscsi/iscsi_target_stat.c
index f1db83077e0a..421d6947dc64 100644
--- a/drivers/target/iscsi/iscsi_target_stat.c
+++ b/drivers/target/iscsi/iscsi_target_stat.c
@@ -23,7 +23,6 @@
#include <linux/export.h>
#include <scsi/iscsi_proto.h>
#include <target/target_core_base.h>
-#include <target/target_core_transport.h>
#include <target/configfs_macros.h>
#include "iscsi_target_core.h"
@@ -746,7 +745,7 @@ static ssize_t iscsi_stat_sess_show_attr_node(
spin_lock_bh(&se_nacl->nacl_sess_lock);
se_sess = se_nacl->nacl_sess;
if (se_sess) {
- sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+ sess = se_sess->fabric_sess_ptr;
if (sess)
ret = snprintf(page, PAGE_SIZE, "%u\n",
sess->sess_ops->SessionType ? 0 : ISCSI_NODE_INDEX);
@@ -770,7 +769,7 @@ static ssize_t iscsi_stat_sess_show_attr_indx(
spin_lock_bh(&se_nacl->nacl_sess_lock);
se_sess = se_nacl->nacl_sess;
if (se_sess) {
- sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+ sess = se_sess->fabric_sess_ptr;
if (sess)
ret = snprintf(page, PAGE_SIZE, "%u\n",
sess->session_index);
@@ -794,7 +793,7 @@ static ssize_t iscsi_stat_sess_show_attr_cmd_pdus(
spin_lock_bh(&se_nacl->nacl_sess_lock);
se_sess = se_nacl->nacl_sess;
if (se_sess) {
- sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+ sess = se_sess->fabric_sess_ptr;
if (sess)
ret = snprintf(page, PAGE_SIZE, "%u\n", sess->cmd_pdus);
}
@@ -817,7 +816,7 @@ static ssize_t iscsi_stat_sess_show_attr_rsp_pdus(
spin_lock_bh(&se_nacl->nacl_sess_lock);
se_sess = se_nacl->nacl_sess;
if (se_sess) {
- sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+ sess = se_sess->fabric_sess_ptr;
if (sess)
ret = snprintf(page, PAGE_SIZE, "%u\n", sess->rsp_pdus);
}
@@ -840,7 +839,7 @@ static ssize_t iscsi_stat_sess_show_attr_txdata_octs(
spin_lock_bh(&se_nacl->nacl_sess_lock);
se_sess = se_nacl->nacl_sess;
if (se_sess) {
- sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+ sess = se_sess->fabric_sess_ptr;
if (sess)
ret = snprintf(page, PAGE_SIZE, "%llu\n",
(unsigned long long)sess->tx_data_octets);
@@ -864,7 +863,7 @@ static ssize_t iscsi_stat_sess_show_attr_rxdata_octs(
spin_lock_bh(&se_nacl->nacl_sess_lock);
se_sess = se_nacl->nacl_sess;
if (se_sess) {
- sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+ sess = se_sess->fabric_sess_ptr;
if (sess)
ret = snprintf(page, PAGE_SIZE, "%llu\n",
(unsigned long long)sess->rx_data_octets);
@@ -888,7 +887,7 @@ static ssize_t iscsi_stat_sess_show_attr_conn_digest_errors(
spin_lock_bh(&se_nacl->nacl_sess_lock);
se_sess = se_nacl->nacl_sess;
if (se_sess) {
- sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+ sess = se_sess->fabric_sess_ptr;
if (sess)
ret = snprintf(page, PAGE_SIZE, "%u\n",
sess->conn_digest_errors);
@@ -912,7 +911,7 @@ static ssize_t iscsi_stat_sess_show_attr_conn_timeout_errors(
spin_lock_bh(&se_nacl->nacl_sess_lock);
se_sess = se_nacl->nacl_sess;
if (se_sess) {
- sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+ sess = se_sess->fabric_sess_ptr;
if (sess)
ret = snprintf(page, PAGE_SIZE, "%u\n",
sess->conn_timeout_errors);
diff --git a/drivers/target/iscsi/iscsi_target_tmr.c b/drivers/target/iscsi/iscsi_target_tmr.c
index 490207eacde9..255ed35da815 100644
--- a/drivers/target/iscsi/iscsi_target_tmr.c
+++ b/drivers/target/iscsi/iscsi_target_tmr.c
@@ -21,7 +21,7 @@
#include <asm/unaligned.h>
#include <scsi/iscsi_proto.h>
#include <target/target_core_base.h>
-#include <target/target_core_transport.h>
+#include <target/target_core_fabric.h>
#include "iscsi_target_core.h"
#include "iscsi_target_seq_pdu_list.h"
diff --git a/drivers/target/iscsi/iscsi_target_tpg.c b/drivers/target/iscsi/iscsi_target_tpg.c
index d4cf2cd25c44..879d8d0fa3fe 100644
--- a/drivers/target/iscsi/iscsi_target_tpg.c
+++ b/drivers/target/iscsi/iscsi_target_tpg.c
@@ -19,10 +19,8 @@
******************************************************************************/
#include <target/target_core_base.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_fabric.h>
#include <target/target_core_configfs.h>
-#include <target/target_core_tpg.h>
#include "iscsi_target_core.h"
#include "iscsi_target_erl0.h"
@@ -72,7 +70,7 @@ int iscsit_load_discovery_tpg(void)
ret = core_tpg_register(
&lio_target_fabric_configfs->tf_ops,
- NULL, &tpg->tpg_se_tpg, (void *)tpg,
+ NULL, &tpg->tpg_se_tpg, tpg,
TRANSPORT_TPG_TYPE_DISCOVERY);
if (ret < 0) {
kfree(tpg);
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c
index 02348f727bd4..a05ca1c4f01c 100644
--- a/drivers/target/iscsi/iscsi_target_util.c
+++ b/drivers/target/iscsi/iscsi_target_util.c
@@ -22,9 +22,7 @@
#include <scsi/scsi_tcq.h>
#include <scsi/iscsi_proto.h>
#include <target/target_core_base.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_tmr.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_fabric.h>
#include <target/target_core_configfs.h>
#include "iscsi_target_core.h"
@@ -289,7 +287,7 @@ struct iscsi_cmd *iscsit_allocate_se_cmd_for_tmr(
}
se_cmd->se_tmr_req = core_tmr_alloc_req(se_cmd,
- (void *)cmd->tmr_req, tcm_function,
+ cmd->tmr_req, tcm_function,
GFP_KERNEL);
if (!se_cmd->se_tmr_req)
goto out;
@@ -1066,7 +1064,7 @@ static void iscsit_handle_nopin_response_timeout(unsigned long data)
if (tiqn) {
spin_lock_bh(&tiqn->sess_err_stats.lock);
strcpy(tiqn->sess_err_stats.last_sess_fail_rem_name,
- (void *)conn->sess->sess_ops->InitiatorName);
+ conn->sess->sess_ops->InitiatorName);
tiqn->sess_err_stats.last_sess_failure_type =
ISCSI_SESS_ERR_CXN_TIMEOUT;
tiqn->sess_err_stats.cxn_timeout_errors++;
diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c
index 81d5832fbbd5..c47ff7f59e57 100644
--- a/drivers/target/loopback/tcm_loop.c
+++ b/drivers/target/loopback/tcm_loop.c
@@ -33,14 +33,9 @@
#include <scsi/scsi_cmnd.h>
#include <target/target_core_base.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_fabric.h>
#include <target/target_core_fabric_configfs.h>
-#include <target/target_core_fabric_lib.h>
#include <target/target_core_configfs.h>
-#include <target/target_core_device.h>
-#include <target/target_core_tpg.h>
-#include <target/target_core_tmr.h>
#include "tcm_loop.h"
@@ -421,11 +416,11 @@ static struct scsi_host_template tcm_loop_driver_template = {
.queuecommand = tcm_loop_queuecommand,
.change_queue_depth = tcm_loop_change_queue_depth,
.eh_device_reset_handler = tcm_loop_device_reset,
- .can_queue = TL_SCSI_CAN_QUEUE,
+ .can_queue = 1024,
.this_id = -1,
- .sg_tablesize = TL_SCSI_SG_TABLESIZE,
- .cmd_per_lun = TL_SCSI_CMD_PER_LUN,
- .max_sectors = TL_SCSI_MAX_SECTORS,
+ .sg_tablesize = 256,
+ .cmd_per_lun = 1024,
+ .max_sectors = 0xFFFF,
.use_clustering = DISABLE_CLUSTERING,
.slave_alloc = tcm_loop_slave_alloc,
.slave_configure = tcm_loop_slave_configure,
@@ -564,8 +559,7 @@ static char *tcm_loop_get_fabric_name(void)
static u8 tcm_loop_get_fabric_proto_ident(struct se_portal_group *se_tpg)
{
- struct tcm_loop_tpg *tl_tpg =
- (struct tcm_loop_tpg *)se_tpg->se_tpg_fabric_ptr;
+ struct tcm_loop_tpg *tl_tpg = se_tpg->se_tpg_fabric_ptr;
struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
/*
* tl_proto_id is set at tcm_loop_configfs.c:tcm_loop_make_scsi_hba()
@@ -592,8 +586,7 @@ static u8 tcm_loop_get_fabric_proto_ident(struct se_portal_group *se_tpg)
static char *tcm_loop_get_endpoint_wwn(struct se_portal_group *se_tpg)
{
- struct tcm_loop_tpg *tl_tpg =
- (struct tcm_loop_tpg *)se_tpg->se_tpg_fabric_ptr;
+ struct tcm_loop_tpg *tl_tpg = se_tpg->se_tpg_fabric_ptr;
/*
* Return the passed NAA identifier for the SAS Target Port
*/
@@ -602,8 +595,7 @@ static char *tcm_loop_get_endpoint_wwn(struct se_portal_group *se_tpg)
static u16 tcm_loop_get_tag(struct se_portal_group *se_tpg)
{
- struct tcm_loop_tpg *tl_tpg =
- (struct tcm_loop_tpg *)se_tpg->se_tpg_fabric_ptr;
+ struct tcm_loop_tpg *tl_tpg = se_tpg->se_tpg_fabric_ptr;
/*
* This Tag is used when forming SCSI Name identifier in EVPD=1 0x83
* to represent the SCSI Target Port.
@@ -623,8 +615,7 @@ static u32 tcm_loop_get_pr_transport_id(
int *format_code,
unsigned char *buf)
{
- struct tcm_loop_tpg *tl_tpg =
- (struct tcm_loop_tpg *)se_tpg->se_tpg_fabric_ptr;
+ struct tcm_loop_tpg *tl_tpg = se_tpg->se_tpg_fabric_ptr;
struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
switch (tl_hba->tl_proto_id) {
@@ -653,8 +644,7 @@ static u32 tcm_loop_get_pr_transport_id_len(
struct t10_pr_registration *pr_reg,
int *format_code)
{
- struct tcm_loop_tpg *tl_tpg =
- (struct tcm_loop_tpg *)se_tpg->se_tpg_fabric_ptr;
+ struct tcm_loop_tpg *tl_tpg = se_tpg->se_tpg_fabric_ptr;
struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
switch (tl_hba->tl_proto_id) {
@@ -687,8 +677,7 @@ static char *tcm_loop_parse_pr_out_transport_id(
u32 *out_tid_len,
char **port_nexus_ptr)
{
- struct tcm_loop_tpg *tl_tpg =
- (struct tcm_loop_tpg *)se_tpg->se_tpg_fabric_ptr;
+ struct tcm_loop_tpg *tl_tpg = se_tpg->se_tpg_fabric_ptr;
struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
switch (tl_hba->tl_proto_id) {
diff --git a/drivers/target/loopback/tcm_loop.h b/drivers/target/loopback/tcm_loop.h
index 6b76c7a22bb0..15a036441471 100644
--- a/drivers/target/loopback/tcm_loop.h
+++ b/drivers/target/loopback/tcm_loop.h
@@ -1,16 +1,7 @@
#define TCM_LOOP_VERSION "v2.1-rc1"
#define TL_WWN_ADDR_LEN 256
#define TL_TPGS_PER_HBA 32
-/*
- * Defaults for struct scsi_host_template tcm_loop_driver_template
- *
- * We use large can_queue and cmd_per_lun here and let TCM enforce
- * the underlying se_device_t->queue_depth.
- */
-#define TL_SCSI_CAN_QUEUE 1024
-#define TL_SCSI_CMD_PER_LUN 1024
-#define TL_SCSI_MAX_SECTORS 1024
-#define TL_SCSI_SG_TABLESIZE 256
+
/*
* Used in tcm_loop_driver_probe() for struct Scsi_Host->max_cmd_len
*/
diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c
index 1dcbef499d6a..1b1edd14f4bf 100644
--- a/drivers/target/target_core_alua.c
+++ b/drivers/target/target_core_alua.c
@@ -32,13 +32,12 @@
#include <scsi/scsi_cmnd.h>
#include <target/target_core_base.h>
-#include <target/target_core_device.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_backend.h>
+#include <target/target_core_fabric.h>
#include <target/target_core_configfs.h>
+#include "target_core_internal.h"
#include "target_core_alua.h"
-#include "target_core_hba.h"
#include "target_core_ua.h"
static int core_alua_check_transition(int state, int *primary);
diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c
index 831468b3163d..2f2235edefff 100644
--- a/drivers/target/target_core_cdb.c
+++ b/drivers/target/target_core_cdb.c
@@ -29,10 +29,11 @@
#include <scsi/scsi.h>
#include <target/target_core_base.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_backend.h>
+#include <target/target_core_fabric.h>
+
+#include "target_core_internal.h"
#include "target_core_ua.h"
-#include "target_core_cdb.h"
static void
target_fill_alua_data(struct se_port *port, unsigned char *buf)
@@ -94,6 +95,18 @@ target_emulate_inquiry_std(struct se_cmd *cmd)
buf[2] = dev->transport->get_device_rev(dev);
/*
+ * NORMACA and HISUP = 0, RESPONSE DATA FORMAT = 2
+ *
+ * SPC4 says:
+ * A RESPONSE DATA FORMAT field set to 2h indicates that the
+ * standard INQUIRY data is in the format defined in this
+ * standard. Response data format values less than 2h are
+ * obsolete. Response data format values greater than 2h are
+ * reserved.
+ */
+ buf[3] = 2;
+
+ /*
* Enable SCCS and TPGS fields for Emulated ALUA
*/
if (dev->se_sub_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED)
@@ -115,11 +128,9 @@ target_emulate_inquiry_std(struct se_cmd *cmd)
goto out;
}
- snprintf((unsigned char *)&buf[8], 8, "LIO-ORG");
- snprintf((unsigned char *)&buf[16], 16, "%s",
- &dev->se_sub_dev->t10_wwn.model[0]);
- snprintf((unsigned char *)&buf[32], 4, "%s",
- &dev->se_sub_dev->t10_wwn.revision[0]);
+ snprintf(&buf[8], 8, "LIO-ORG");
+ snprintf(&buf[16], 16, "%s", dev->se_sub_dev->t10_wwn.model);
+ snprintf(&buf[32], 4, "%s", dev->se_sub_dev->t10_wwn.revision);
buf[4] = 31; /* Set additional length to 31 */
out:
@@ -138,8 +149,7 @@ target_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf)
SDF_EMULATED_VPD_UNIT_SERIAL) {
u32 unit_serial_len;
- unit_serial_len =
- strlen(&dev->se_sub_dev->t10_wwn.unit_serial[0]);
+ unit_serial_len = strlen(dev->se_sub_dev->t10_wwn.unit_serial);
unit_serial_len++; /* For NULL Terminator */
if (((len + 4) + unit_serial_len) > cmd->data_length) {
@@ -148,8 +158,8 @@ target_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf)
buf[3] = (len & 0xff);
return 0;
}
- len += sprintf((unsigned char *)&buf[4], "%s",
- &dev->se_sub_dev->t10_wwn.unit_serial[0]);
+ len += sprintf(&buf[4], "%s",
+ dev->se_sub_dev->t10_wwn.unit_serial);
len++; /* Extra Byte for NULL Terminator */
buf[3] = len;
}
@@ -279,14 +289,13 @@ check_t10_vend_desc:
len += (prod_len + unit_serial_len);
goto check_port;
}
- id_len += sprintf((unsigned char *)&buf[off+12],
- "%s:%s", prod,
+ id_len += sprintf(&buf[off+12], "%s:%s", prod,
&dev->se_sub_dev->t10_wwn.unit_serial[0]);
}
buf[off] = 0x2; /* ASCII */
buf[off+1] = 0x1; /* T10 Vendor ID */
buf[off+2] = 0x0;
- memcpy((unsigned char *)&buf[off+4], "LIO-ORG", 8);
+ memcpy(&buf[off+4], "LIO-ORG", 8);
/* Extra Byte for NULL Terminator */
id_len++;
/* Identifier Length */
diff --git a/drivers/target/target_core_cdb.h b/drivers/target/target_core_cdb.h
deleted file mode 100644
index ad6b1e393001..000000000000
--- a/drivers/target/target_core_cdb.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef TARGET_CORE_CDB_H
-#define TARGET_CORE_CDB_H
-
-int target_emulate_inquiry(struct se_task *task);
-int target_emulate_readcapacity(struct se_task *task);
-int target_emulate_readcapacity_16(struct se_task *task);
-int target_emulate_modesense(struct se_task *task);
-int target_emulate_request_sense(struct se_task *task);
-int target_emulate_unmap(struct se_task *task);
-int target_emulate_write_same(struct se_task *task);
-int target_emulate_synchronize_cache(struct se_task *task);
-int target_emulate_noop(struct se_task *task);
-
-#endif /* TARGET_CORE_CDB_H */
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
index 93d4f6a1b798..0955bb8979fb 100644
--- a/drivers/target/target_core_configfs.c
+++ b/drivers/target/target_core_configfs.c
@@ -39,18 +39,16 @@
#include <linux/spinlock.h>
#include <target/target_core_base.h>
-#include <target/target_core_device.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_backend.h>
+#include <target/target_core_fabric.h>
#include <target/target_core_fabric_configfs.h>
#include <target/target_core_configfs.h>
#include <target/configfs_macros.h>
+#include "target_core_internal.h"
#include "target_core_alua.h"
-#include "target_core_hba.h"
#include "target_core_pr.h"
#include "target_core_rd.h"
-#include "target_core_stat.h"
extern struct t10_alua_lu_gp *default_lu_gp;
@@ -1452,7 +1450,7 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
return -ENOMEM;
orig = opts;
- while ((ptr = strsep(&opts, ",")) != NULL) {
+ while ((ptr = strsep(&opts, ",\n")) != NULL) {
if (!*ptr)
continue;
@@ -1631,7 +1629,7 @@ static struct config_item_type target_core_dev_pr_cit = {
static ssize_t target_core_show_dev_info(void *p, char *page)
{
- struct se_subsystem_dev *se_dev = (struct se_subsystem_dev *)p;
+ struct se_subsystem_dev *se_dev = p;
struct se_hba *hba = se_dev->se_dev_hba;
struct se_subsystem_api *t = hba->transport;
int bl = 0;
@@ -1659,7 +1657,7 @@ static ssize_t target_core_store_dev_control(
const char *page,
size_t count)
{
- struct se_subsystem_dev *se_dev = (struct se_subsystem_dev *)p;
+ struct se_subsystem_dev *se_dev = p;
struct se_hba *hba = se_dev->se_dev_hba;
struct se_subsystem_api *t = hba->transport;
@@ -1682,7 +1680,7 @@ static struct target_core_configfs_attribute target_core_attr_dev_control = {
static ssize_t target_core_show_dev_alias(void *p, char *page)
{
- struct se_subsystem_dev *se_dev = (struct se_subsystem_dev *)p;
+ struct se_subsystem_dev *se_dev = p;
if (!(se_dev->su_dev_flags & SDF_USING_ALIAS))
return 0;
@@ -1695,7 +1693,7 @@ static ssize_t target_core_store_dev_alias(
const char *page,
size_t count)
{
- struct se_subsystem_dev *se_dev = (struct se_subsystem_dev *)p;
+ struct se_subsystem_dev *se_dev = p;
struct se_hba *hba = se_dev->se_dev_hba;
ssize_t read_bytes;
@@ -1710,6 +1708,9 @@ static ssize_t target_core_store_dev_alias(
read_bytes = snprintf(&se_dev->se_dev_alias[0], SE_DEV_ALIAS_LEN,
"%s", page);
+ if (se_dev->se_dev_alias[read_bytes - 1] == '\n')
+ se_dev->se_dev_alias[read_bytes - 1] = '\0';
+
pr_debug("Target_Core_ConfigFS: %s/%s set alias: %s\n",
config_item_name(&hba->hba_group.cg_item),
config_item_name(&se_dev->se_dev_group.cg_item),
@@ -1728,7 +1729,7 @@ static struct target_core_configfs_attribute target_core_attr_dev_alias = {
static ssize_t target_core_show_dev_udev_path(void *p, char *page)
{
- struct se_subsystem_dev *se_dev = (struct se_subsystem_dev *)p;
+ struct se_subsystem_dev *se_dev = p;
if (!(se_dev->su_dev_flags & SDF_USING_UDEV_PATH))
return 0;
@@ -1741,7 +1742,7 @@ static ssize_t target_core_store_dev_udev_path(
const char *page,
size_t count)
{
- struct se_subsystem_dev *se_dev = (struct se_subsystem_dev *)p;
+ struct se_subsystem_dev *se_dev = p;
struct se_hba *hba = se_dev->se_dev_hba;
ssize_t read_bytes;
@@ -1756,6 +1757,9 @@ static ssize_t target_core_store_dev_udev_path(
read_bytes = snprintf(&se_dev->se_dev_udev_path[0], SE_UDEV_PATH_LEN,
"%s", page);
+ if (se_dev->se_dev_udev_path[read_bytes - 1] == '\n')
+ se_dev->se_dev_udev_path[read_bytes - 1] = '\0';
+
pr_debug("Target_Core_ConfigFS: %s/%s set udev_path: %s\n",
config_item_name(&hba->hba_group.cg_item),
config_item_name(&se_dev->se_dev_group.cg_item),
@@ -1777,7 +1781,7 @@ static ssize_t target_core_store_dev_enable(
const char *page,
size_t count)
{
- struct se_subsystem_dev *se_dev = (struct se_subsystem_dev *)p;
+ struct se_subsystem_dev *se_dev = p;
struct se_device *dev;
struct se_hba *hba = se_dev->se_dev_hba;
struct se_subsystem_api *t = hba->transport;
@@ -1822,7 +1826,7 @@ static struct target_core_configfs_attribute target_core_attr_dev_enable = {
static ssize_t target_core_show_alua_lu_gp(void *p, char *page)
{
struct se_device *dev;
- struct se_subsystem_dev *su_dev = (struct se_subsystem_dev *)p;
+ struct se_subsystem_dev *su_dev = p;
struct config_item *lu_ci;
struct t10_alua_lu_gp *lu_gp;
struct t10_alua_lu_gp_member *lu_gp_mem;
@@ -1860,7 +1864,7 @@ static ssize_t target_core_store_alua_lu_gp(
size_t count)
{
struct se_device *dev;
- struct se_subsystem_dev *su_dev = (struct se_subsystem_dev *)p;
+ struct se_subsystem_dev *su_dev = p;
struct se_hba *hba = su_dev->se_dev_hba;
struct t10_alua_lu_gp *lu_gp = NULL, *lu_gp_new = NULL;
struct t10_alua_lu_gp_member *lu_gp_mem;
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c
index 9b8639425472..0c5992f0d946 100644
--- a/drivers/target/target_core_device.c
+++ b/drivers/target/target_core_device.c
@@ -42,13 +42,11 @@
#include <scsi/scsi_device.h>
#include <target/target_core_base.h>
-#include <target/target_core_device.h>
-#include <target/target_core_tpg.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_backend.h>
+#include <target/target_core_fabric.h>
+#include "target_core_internal.h"
#include "target_core_alua.h"
-#include "target_core_hba.h"
#include "target_core_pr.h"
#include "target_core_ua.h"
@@ -1134,8 +1132,6 @@ int se_dev_set_emulate_rest_reord(struct se_device *dev, int flag)
*/
int se_dev_set_queue_depth(struct se_device *dev, u32 queue_depth)
{
- u32 orig_queue_depth = dev->queue_depth;
-
if (atomic_read(&dev->dev_export_obj.obj_access_count)) {
pr_err("dev[%p]: Unable to change SE Device TCQ while"
" dev_export_obj: %d count exists\n", dev,
@@ -1169,11 +1165,6 @@ int se_dev_set_queue_depth(struct se_device *dev, u32 queue_depth)
}
dev->se_sub_dev->se_dev_attrib.queue_depth = dev->queue_depth = queue_depth;
- if (queue_depth > orig_queue_depth)
- atomic_add(queue_depth - orig_queue_depth, &dev->depth_left);
- else if (queue_depth < orig_queue_depth)
- atomic_sub(orig_queue_depth - queue_depth, &dev->depth_left);
-
pr_debug("dev[%p]: SE Device TCQ Depth changed to: %u\n",
dev, queue_depth);
return 0;
diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c
index 09b6f8729f91..4f77cce22646 100644
--- a/drivers/target/target_core_fabric_configfs.c
+++ b/drivers/target/target_core_fabric_configfs.c
@@ -36,18 +36,14 @@
#include <linux/configfs.h>
#include <target/target_core_base.h>
-#include <target/target_core_device.h>
-#include <target/target_core_tpg.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_fabric.h>
#include <target/target_core_fabric_configfs.h>
#include <target/target_core_configfs.h>
#include <target/configfs_macros.h>
+#include "target_core_internal.h"
#include "target_core_alua.h"
-#include "target_core_hba.h"
#include "target_core_pr.h"
-#include "target_core_stat.h"
#define TF_CIT_SETUP(_name, _item_ops, _group_ops, _attrs) \
static void target_fabric_setup_##_name##_cit(struct target_fabric_configfs *tf) \
diff --git a/drivers/target/target_core_fabric_lib.c b/drivers/target/target_core_fabric_lib.c
index ec4249be617e..283a36e464e6 100644
--- a/drivers/target/target_core_fabric_lib.c
+++ b/drivers/target/target_core_fabric_lib.c
@@ -34,13 +34,10 @@
#include <scsi/scsi_cmnd.h>
#include <target/target_core_base.h>
-#include <target/target_core_device.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_lib.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_fabric.h>
#include <target/target_core_configfs.h>
-#include "target_core_hba.h"
+#include "target_core_internal.h"
#include "target_core_pr.h"
/*
@@ -402,7 +399,7 @@ char *iscsi_parse_pr_out_transport_id(
add_len = ((buf[2] >> 8) & 0xff);
add_len |= (buf[3] & 0xff);
- tid_len = strlen((char *)&buf[4]);
+ tid_len = strlen(&buf[4]);
tid_len += 4; /* Add four bytes for iSCSI Transport ID header */
tid_len += 1; /* Add one byte for NULL terminator */
padding = ((-tid_len) & 3);
@@ -423,11 +420,11 @@ char *iscsi_parse_pr_out_transport_id(
* format.
*/
if (format_code == 0x40) {
- p = strstr((char *)&buf[4], ",i,0x");
+ p = strstr(&buf[4], ",i,0x");
if (!p) {
pr_err("Unable to locate \",i,0x\" seperator"
" for Initiator port identifier: %s\n",
- (char *)&buf[4]);
+ &buf[4]);
return NULL;
}
*p = '\0'; /* Terminate iSCSI Name */
diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c
index b4864fba4ef0..7ed58e2df791 100644
--- a/drivers/target/target_core_file.c
+++ b/drivers/target/target_core_file.c
@@ -37,8 +37,7 @@
#include <scsi/scsi_host.h>
#include <target/target_core_base.h>
-#include <target/target_core_device.h>
-#include <target/target_core_transport.h>
+#include <target/target_core_backend.h>
#include "target_core_file.h"
@@ -86,7 +85,7 @@ static void fd_detach_hba(struct se_hba *hba)
static void *fd_allocate_virtdevice(struct se_hba *hba, const char *name)
{
struct fd_dev *fd_dev;
- struct fd_host *fd_host = (struct fd_host *) hba->hba_ptr;
+ struct fd_host *fd_host = hba->hba_ptr;
fd_dev = kzalloc(sizeof(struct fd_dev), GFP_KERNEL);
if (!fd_dev) {
@@ -114,8 +113,8 @@ static struct se_device *fd_create_virtdevice(
struct se_device *dev;
struct se_dev_limits dev_limits;
struct queue_limits *limits;
- struct fd_dev *fd_dev = (struct fd_dev *) p;
- struct fd_host *fd_host = (struct fd_host *) hba->hba_ptr;
+ struct fd_dev *fd_dev = p;
+ struct fd_host *fd_host = hba->hba_ptr;
mm_segment_t old_fs;
struct file *file;
struct inode *inode = NULL;
@@ -240,7 +239,7 @@ fail:
*/
static void fd_free_device(void *p)
{
- struct fd_dev *fd_dev = (struct fd_dev *) p;
+ struct fd_dev *fd_dev = p;
if (fd_dev->fd_file) {
filp_close(fd_dev->fd_file, NULL);
@@ -498,7 +497,7 @@ static ssize_t fd_set_configfs_dev_params(
orig = opts;
- while ((ptr = strsep(&opts, ",")) != NULL) {
+ while ((ptr = strsep(&opts, ",\n")) != NULL) {
if (!*ptr)
continue;
@@ -559,7 +558,7 @@ out:
static ssize_t fd_check_configfs_dev_params(struct se_hba *hba, struct se_subsystem_dev *se_dev)
{
- struct fd_dev *fd_dev = (struct fd_dev *) se_dev->se_dev_su_ptr;
+ struct fd_dev *fd_dev = se_dev->se_dev_su_ptr;
if (!(fd_dev->fbd_flags & FBDF_HAS_PATH)) {
pr_err("Missing fd_dev_name=\n");
diff --git a/drivers/target/target_core_hba.c b/drivers/target/target_core_hba.c
index c68019d6c406..3dd1bd4b6f71 100644
--- a/drivers/target/target_core_hba.c
+++ b/drivers/target/target_core_hba.c
@@ -37,11 +37,10 @@
#include <net/tcp.h>
#include <target/target_core_base.h>
-#include <target/target_core_device.h>
-#include <target/target_core_tpg.h>
-#include <target/target_core_transport.h>
+#include <target/target_core_backend.h>
+#include <target/target_core_fabric.h>
-#include "target_core_hba.h"
+#include "target_core_internal.h"
static LIST_HEAD(subsystem_list);
static DEFINE_MUTEX(subsystem_mutex);
diff --git a/drivers/target/target_core_hba.h b/drivers/target/target_core_hba.h
deleted file mode 100644
index bb0fea5f730c..000000000000
--- a/drivers/target/target_core_hba.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef TARGET_CORE_HBA_H
-#define TARGET_CORE_HBA_H
-
-extern struct se_hba *core_alloc_hba(const char *, u32, u32);
-extern int core_delete_hba(struct se_hba *);
-
-#endif /* TARGET_CORE_HBA_H */
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
index 4aa992204438..cc8e6b58ef20 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -42,8 +42,7 @@
#include <scsi/scsi_host.h>
#include <target/target_core_base.h>
-#include <target/target_core_device.h>
-#include <target/target_core_transport.h>
+#include <target/target_core_backend.h>
#include "target_core_iblock.h"
@@ -391,7 +390,7 @@ static ssize_t iblock_set_configfs_dev_params(struct se_hba *hba,
orig = opts;
- while ((ptr = strsep(&opts, ",")) != NULL) {
+ while ((ptr = strsep(&opts, ",\n")) != NULL) {
if (!*ptr)
continue;
@@ -465,7 +464,7 @@ static ssize_t iblock_show_configfs_dev_params(
if (bd) {
bl += sprintf(b + bl, "Major: %d Minor: %d %s\n",
MAJOR(bd->bd_dev), MINOR(bd->bd_dev), (!bd->bd_contains) ?
- "" : (bd->bd_holder == (struct iblock_dev *)ibd) ?
+ "" : (bd->bd_holder == ibd) ?
"CLAIMED: IBLOCK" : "CLAIMED: OS");
} else {
bl += sprintf(b + bl, "Major: 0 Minor: 0\n");
diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h
new file mode 100644
index 000000000000..26f135e94f6e
--- /dev/null
+++ b/drivers/target/target_core_internal.h
@@ -0,0 +1,123 @@
+#ifndef TARGET_CORE_INTERNAL_H
+#define TARGET_CORE_INTERNAL_H
+
+/* target_core_alua.c */
+extern struct t10_alua_lu_gp *default_lu_gp;
+
+/* target_core_cdb.c */
+int target_emulate_inquiry(struct se_task *task);
+int target_emulate_readcapacity(struct se_task *task);
+int target_emulate_readcapacity_16(struct se_task *task);
+int target_emulate_modesense(struct se_task *task);
+int target_emulate_request_sense(struct se_task *task);
+int target_emulate_unmap(struct se_task *task);
+int target_emulate_write_same(struct se_task *task);
+int target_emulate_synchronize_cache(struct se_task *task);
+int target_emulate_noop(struct se_task *task);
+
+/* target_core_device.c */
+struct se_dev_entry *core_get_se_deve_from_rtpi(struct se_node_acl *, u16);
+int core_free_device_list_for_node(struct se_node_acl *,
+ struct se_portal_group *);
+void core_dec_lacl_count(struct se_node_acl *, struct se_cmd *);
+void core_update_device_list_access(u32, u32, struct se_node_acl *);
+int core_update_device_list_for_node(struct se_lun *, struct se_lun_acl *,
+ u32, u32, struct se_node_acl *, struct se_portal_group *, int);
+void core_clear_lun_from_tpg(struct se_lun *, struct se_portal_group *);
+int core_dev_export(struct se_device *, struct se_portal_group *,
+ struct se_lun *);
+void core_dev_unexport(struct se_device *, struct se_portal_group *,
+ struct se_lun *);
+int target_report_luns(struct se_task *);
+void se_release_device_for_hba(struct se_device *);
+void se_release_vpd_for_dev(struct se_device *);
+int se_free_virtual_device(struct se_device *, struct se_hba *);
+int se_dev_check_online(struct se_device *);
+int se_dev_check_shutdown(struct se_device *);
+void se_dev_set_default_attribs(struct se_device *, struct se_dev_limits *);
+int se_dev_set_task_timeout(struct se_device *, u32);
+int se_dev_set_max_unmap_lba_count(struct se_device *, u32);
+int se_dev_set_max_unmap_block_desc_count(struct se_device *, u32);
+int se_dev_set_unmap_granularity(struct se_device *, u32);
+int se_dev_set_unmap_granularity_alignment(struct se_device *, u32);
+int se_dev_set_emulate_dpo(struct se_device *, int);
+int se_dev_set_emulate_fua_write(struct se_device *, int);
+int se_dev_set_emulate_fua_read(struct se_device *, int);
+int se_dev_set_emulate_write_cache(struct se_device *, int);
+int se_dev_set_emulate_ua_intlck_ctrl(struct se_device *, int);
+int se_dev_set_emulate_tas(struct se_device *, int);
+int se_dev_set_emulate_tpu(struct se_device *, int);
+int se_dev_set_emulate_tpws(struct se_device *, int);
+int se_dev_set_enforce_pr_isids(struct se_device *, int);
+int se_dev_set_is_nonrot(struct se_device *, int);
+int se_dev_set_emulate_rest_reord(struct se_device *dev, int);
+int se_dev_set_queue_depth(struct se_device *, u32);
+int se_dev_set_max_sectors(struct se_device *, u32);
+int se_dev_set_optimal_sectors(struct se_device *, u32);
+int se_dev_set_block_size(struct se_device *, u32);
+struct se_lun *core_dev_add_lun(struct se_portal_group *, struct se_hba *,
+ struct se_device *, u32);
+int core_dev_del_lun(struct se_portal_group *, u32);
+struct se_lun *core_get_lun_from_tpg(struct se_portal_group *, u32);
+struct se_lun_acl *core_dev_init_initiator_node_lun_acl(struct se_portal_group *,
+ u32, char *, int *);
+int core_dev_add_initiator_node_lun_acl(struct se_portal_group *,
+ struct se_lun_acl *, u32, u32);
+int core_dev_del_initiator_node_lun_acl(struct se_portal_group *,
+ struct se_lun *, struct se_lun_acl *);
+void core_dev_free_initiator_node_lun_acl(struct se_portal_group *,
+ struct se_lun_acl *lacl);
+int core_dev_setup_virtual_lun0(void);
+void core_dev_release_virtual_lun0(void);
+
+/* target_core_hba.c */
+struct se_hba *core_alloc_hba(const char *, u32, u32);
+int core_delete_hba(struct se_hba *);
+
+/* target_core_tmr.c */
+int core_tmr_lun_reset(struct se_device *, struct se_tmr_req *,
+ struct list_head *, struct se_cmd *);
+
+/* target_core_tpg.c */
+extern struct se_device *g_lun0_dev;
+
+struct se_node_acl *__core_tpg_get_initiator_node_acl(struct se_portal_group *tpg,
+ const char *);
+struct se_node_acl *core_tpg_get_initiator_node_acl(struct se_portal_group *tpg,
+ unsigned char *);
+void core_tpg_add_node_to_devs(struct se_node_acl *, struct se_portal_group *);
+void core_tpg_wait_for_nacl_pr_ref(struct se_node_acl *);
+struct se_lun *core_tpg_pre_addlun(struct se_portal_group *, u32);
+int core_tpg_post_addlun(struct se_portal_group *, struct se_lun *,
+ u32, void *);
+struct se_lun *core_tpg_pre_dellun(struct se_portal_group *, u32, int *);
+int core_tpg_post_dellun(struct se_portal_group *, struct se_lun *);
+
+/* target_core_transport.c */
+extern struct kmem_cache *se_tmr_req_cache;
+
+int init_se_kmem_caches(void);
+void release_se_kmem_caches(void);
+u32 scsi_get_new_index(scsi_index_t);
+void transport_subsystem_check_init(void);
+void transport_cmd_finish_abort(struct se_cmd *, int);
+void __transport_remove_task_from_execute_queue(struct se_task *,
+ struct se_device *);
+unsigned char *transport_dump_cmd_direction(struct se_cmd *);
+void transport_dump_dev_state(struct se_device *, char *, int *);
+void transport_dump_dev_info(struct se_device *, struct se_lun *,
+ unsigned long long, char *, int *);
+void transport_dump_vpd_proto_id(struct t10_vpd *, unsigned char *, int);
+int transport_dump_vpd_assoc(struct t10_vpd *, unsigned char *, int);
+int transport_dump_vpd_ident_type(struct t10_vpd *, unsigned char *, int);
+int transport_dump_vpd_ident(struct t10_vpd *, unsigned char *, int);
+bool target_stop_task(struct se_task *task, unsigned long *flags);
+int transport_clear_lun_from_sessions(struct se_lun *);
+void transport_send_task_abort(struct se_cmd *);
+
+/* target_core_stat.c */
+void target_stat_setup_dev_default_groups(struct se_subsystem_dev *);
+void target_stat_setup_port_default_groups(struct se_lun *);
+void target_stat_setup_mappedlun_default_groups(struct se_lun_acl *);
+
+#endif /* TARGET_CORE_INTERNAL_H */
diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c
index 95dee7074aeb..429ad7291664 100644
--- a/drivers/target/target_core_pr.c
+++ b/drivers/target/target_core_pr.c
@@ -33,14 +33,11 @@
#include <asm/unaligned.h>
#include <target/target_core_base.h>
-#include <target/target_core_device.h>
-#include <target/target_core_tmr.h>
-#include <target/target_core_tpg.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_backend.h>
+#include <target/target_core_fabric.h>
#include <target/target_core_configfs.h>
-#include "target_core_hba.h"
+#include "target_core_internal.h"
#include "target_core_pr.h"
#include "target_core_ua.h"
@@ -2984,21 +2981,6 @@ static void core_scsi3_release_preempt_and_abort(
}
}
-int core_scsi3_check_cdb_abort_and_preempt(
- struct list_head *preempt_and_abort_list,
- struct se_cmd *cmd)
-{
- struct t10_pr_registration *pr_reg, *pr_reg_tmp;
-
- list_for_each_entry_safe(pr_reg, pr_reg_tmp, preempt_and_abort_list,
- pr_reg_abort_list) {
- if (pr_reg->pr_res_key == cmd->pr_res_key)
- return 0;
- }
-
- return 1;
-}
-
static int core_scsi3_pro_preempt(
struct se_cmd *cmd,
int type,
diff --git a/drivers/target/target_core_pr.h b/drivers/target/target_core_pr.h
index b97f6940dd05..7a233feb7e99 100644
--- a/drivers/target/target_core_pr.h
+++ b/drivers/target/target_core_pr.h
@@ -60,8 +60,6 @@ extern void core_scsi3_free_pr_reg_from_nacl(struct se_device *,
struct se_node_acl *);
extern void core_scsi3_free_all_registrations(struct se_device *);
extern unsigned char *core_scsi3_pr_dump_type(int);
-extern int core_scsi3_check_cdb_abort_and_preempt(struct list_head *,
- struct se_cmd *);
extern int target_scsi3_emulate_pr_in(struct se_task *task);
extern int target_scsi3_emulate_pr_out(struct se_task *task);
diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c
index 8b15e56b0384..d35467d42e12 100644
--- a/drivers/target/target_core_pscsi.c
+++ b/drivers/target/target_core_pscsi.c
@@ -44,8 +44,7 @@
#include <scsi/scsi_tcq.h>
#include <target/target_core_base.h>
-#include <target/target_core_device.h>
-#include <target/target_core_transport.h>
+#include <target/target_core_backend.h>
#include "target_core_pscsi.h"
@@ -105,7 +104,7 @@ static void pscsi_detach_hba(struct se_hba *hba)
static int pscsi_pmode_enable_hba(struct se_hba *hba, unsigned long mode_flag)
{
- struct pscsi_hba_virt *phv = (struct pscsi_hba_virt *)hba->hba_ptr;
+ struct pscsi_hba_virt *phv = hba->hba_ptr;
struct Scsi_Host *sh = phv->phv_lld_host;
/*
* Release the struct Scsi_Host
@@ -351,7 +350,6 @@ static struct se_device *pscsi_add_device_to_list(
* scsi_device_put() and the pdv->pdv_sd cleared.
*/
pdv->pdv_sd = sd;
-
dev = transport_add_device_to_core_hba(hba, &pscsi_template,
se_dev, dev_flags, pdv,
&dev_limits, NULL, NULL);
@@ -406,7 +404,7 @@ static struct se_device *pscsi_create_type_disk(
__releases(sh->host_lock)
{
struct se_device *dev;
- struct pscsi_hba_virt *phv = (struct pscsi_hba_virt *)pdv->pdv_se_hba->hba_ptr;
+ struct pscsi_hba_virt *phv = pdv->pdv_se_hba->hba_ptr;
struct Scsi_Host *sh = sd->host;
struct block_device *bd;
u32 dev_flags = 0;
@@ -454,7 +452,7 @@ static struct se_device *pscsi_create_type_rom(
__releases(sh->host_lock)
{
struct se_device *dev;
- struct pscsi_hba_virt *phv = (struct pscsi_hba_virt *)pdv->pdv_se_hba->hba_ptr;
+ struct pscsi_hba_virt *phv = pdv->pdv_se_hba->hba_ptr;
struct Scsi_Host *sh = sd->host;
u32 dev_flags = 0;
@@ -489,7 +487,7 @@ static struct se_device *pscsi_create_type_other(
__releases(sh->host_lock)
{
struct se_device *dev;
- struct pscsi_hba_virt *phv = (struct pscsi_hba_virt *)pdv->pdv_se_hba->hba_ptr;
+ struct pscsi_hba_virt *phv = pdv->pdv_se_hba->hba_ptr;
struct Scsi_Host *sh = sd->host;
u32 dev_flags = 0;
@@ -510,10 +508,10 @@ static struct se_device *pscsi_create_virtdevice(
struct se_subsystem_dev *se_dev,
void *p)
{
- struct pscsi_dev_virt *pdv = (struct pscsi_dev_virt *)p;
+ struct pscsi_dev_virt *pdv = p;
struct se_device *dev;
struct scsi_device *sd;
- struct pscsi_hba_virt *phv = (struct pscsi_hba_virt *)hba->hba_ptr;
+ struct pscsi_hba_virt *phv = hba->hba_ptr;
struct Scsi_Host *sh = phv->phv_lld_host;
int legacy_mode_enable = 0;
@@ -818,7 +816,7 @@ static ssize_t pscsi_set_configfs_dev_params(struct se_hba *hba,
orig = opts;
- while ((ptr = strsep(&opts, ",")) != NULL) {
+ while ((ptr = strsep(&opts, ",\n")) != NULL) {
if (!*ptr)
continue;
@@ -1144,7 +1142,7 @@ static unsigned char *pscsi_get_sense_buffer(struct se_task *task)
{
struct pscsi_plugin_task *pt = PSCSI_TASK(task);
- return (unsigned char *)&pt->pscsi_sense[0];
+ return pt->pscsi_sense;
}
/* pscsi_get_device_rev():
diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c
index 02e51faa2f4e..8b68f7b82631 100644
--- a/drivers/target/target_core_rd.c
+++ b/drivers/target/target_core_rd.c
@@ -37,9 +37,7 @@
#include <scsi/scsi_host.h>
#include <target/target_core_base.h>
-#include <target/target_core_device.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_backend.h>
#include "target_core_rd.h"
@@ -474,7 +472,7 @@ static ssize_t rd_set_configfs_dev_params(
orig = opts;
- while ((ptr = strsep(&opts, ",")) != NULL) {
+ while ((ptr = strsep(&opts, ",\n")) != NULL) {
if (!*ptr)
continue;
diff --git a/drivers/target/target_core_stat.c b/drivers/target/target_core_stat.c
index 874152aed94a..f8c2d2cc3431 100644
--- a/drivers/target/target_core_stat.c
+++ b/drivers/target/target_core_stat.c
@@ -43,12 +43,12 @@
#include <scsi/scsi_host.h>
#include <target/target_core_base.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_backend.h>
+#include <target/target_core_fabric.h>
#include <target/target_core_configfs.h>
#include <target/configfs_macros.h>
-#include "target_core_hba.h"
+#include "target_core_internal.h"
#ifndef INITIAL_JIFFIES
#define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-300*HZ))
@@ -1755,8 +1755,7 @@ static ssize_t target_stat_scsi_att_intr_port_show_attr_port_ident(
/* scsiAttIntrPortName+scsiAttIntrPortIdentifier */
memset(buf, 0, 64);
if (tpg->se_tpg_tfo->sess_get_initiator_sid != NULL)
- tpg->se_tpg_tfo->sess_get_initiator_sid(se_sess,
- (unsigned char *)&buf[0], 64);
+ tpg->se_tpg_tfo->sess_get_initiator_sid(se_sess, buf, 64);
ret = snprintf(page, PAGE_SIZE, "%s+i+%s\n", nacl->initiatorname, buf);
spin_unlock_irq(&nacl->nacl_sess_lock);
diff --git a/drivers/target/target_core_stat.h b/drivers/target/target_core_stat.h
deleted file mode 100644
index 86c252f9ea47..000000000000
--- a/drivers/target/target_core_stat.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef TARGET_CORE_STAT_H
-#define TARGET_CORE_STAT_H
-
-extern void target_stat_setup_dev_default_groups(struct se_subsystem_dev *);
-extern void target_stat_setup_port_default_groups(struct se_lun *);
-extern void target_stat_setup_mappedlun_default_groups(struct se_lun_acl *);
-
-#endif /*** TARGET_CORE_STAT_H ***/
diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c
index 684522805a1f..dcb0618c9388 100644
--- a/drivers/target/target_core_tmr.c
+++ b/drivers/target/target_core_tmr.c
@@ -32,12 +32,11 @@
#include <scsi/scsi_cmnd.h>
#include <target/target_core_base.h>
-#include <target/target_core_device.h>
-#include <target/target_core_tmr.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_backend.h>
+#include <target/target_core_fabric.h>
#include <target/target_core_configfs.h>
+#include "target_core_internal.h"
#include "target_core_alua.h"
#include "target_core_pr.h"
@@ -101,6 +100,21 @@ static void core_tmr_handle_tas_abort(
transport_cmd_finish_abort(cmd, 0);
}
+static int target_check_cdb_and_preempt(struct list_head *list,
+ struct se_cmd *cmd)
+{
+ struct t10_pr_registration *reg;
+
+ if (!list)
+ return 0;
+ list_for_each_entry(reg, list, pr_reg_abort_list) {
+ if (reg->pr_res_key == cmd->pr_res_key)
+ return 0;
+ }
+
+ return 1;
+}
+
static void core_tmr_drain_tmr_list(
struct se_device *dev,
struct se_tmr_req *tmr,
@@ -132,9 +146,7 @@ static void core_tmr_drain_tmr_list(
* parameter (eg: for PROUT PREEMPT_AND_ABORT service action
* skip non regisration key matching TMRs.
*/
- if (preempt_and_abort_list &&
- (core_scsi3_check_cdb_abort_and_preempt(
- preempt_and_abort_list, cmd) != 0))
+ if (target_check_cdb_and_preempt(preempt_and_abort_list, cmd))
continue;
spin_lock(&cmd->t_state_lock);
@@ -211,9 +223,7 @@ static void core_tmr_drain_task_list(
* For PREEMPT_AND_ABORT usage, only process commands
* with a matching reservation key.
*/
- if (preempt_and_abort_list &&
- (core_scsi3_check_cdb_abort_and_preempt(
- preempt_and_abort_list, cmd) != 0))
+ if (target_check_cdb_and_preempt(preempt_and_abort_list, cmd))
continue;
/*
* Not aborting PROUT PREEMPT_AND_ABORT CDB..
@@ -222,7 +232,7 @@ static void core_tmr_drain_task_list(
continue;
list_move_tail(&task->t_state_list, &drain_task_list);
- atomic_set(&task->task_state_active, 0);
+ task->t_state_active = false;
/*
* Remove from task execute list before processing drain_task_list
*/
@@ -321,9 +331,7 @@ static void core_tmr_drain_cmd_list(
* For PREEMPT_AND_ABORT usage, only process commands
* with a matching reservation key.
*/
- if (preempt_and_abort_list &&
- (core_scsi3_check_cdb_abort_and_preempt(
- preempt_and_abort_list, cmd) != 0))
+ if (target_check_cdb_and_preempt(preempt_and_abort_list, cmd))
continue;
/*
* Not aborting PROUT PREEMPT_AND_ABORT CDB..
diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c
index 8ddd133025b9..b7668029bb31 100644
--- a/drivers/target/target_core_tpg.c
+++ b/drivers/target/target_core_tpg.c
@@ -39,13 +39,10 @@
#include <scsi/scsi_cmnd.h>
#include <target/target_core_base.h>
-#include <target/target_core_device.h>
-#include <target/target_core_tpg.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_backend.h>
+#include <target/target_core_fabric.h>
-#include "target_core_hba.h"
-#include "target_core_stat.h"
+#include "target_core_internal.h"
extern struct se_device *g_lun0_dev;
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 0257658e2e3e..d3ddd1361949 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -45,16 +45,12 @@
#include <scsi/scsi_tcq.h>
#include <target/target_core_base.h>
-#include <target/target_core_device.h>
-#include <target/target_core_tmr.h>
-#include <target/target_core_tpg.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_backend.h>
+#include <target/target_core_fabric.h>
#include <target/target_core_configfs.h>
+#include "target_core_internal.h"
#include "target_core_alua.h"
-#include "target_core_cdb.h"
-#include "target_core_hba.h"
#include "target_core_pr.h"
#include "target_core_ua.h"
@@ -72,7 +68,7 @@ struct kmem_cache *t10_alua_tg_pt_gp_mem_cache;
static int transport_generic_write_pending(struct se_cmd *);
static int transport_processing_thread(void *param);
-static int __transport_execute_tasks(struct se_device *dev);
+static int __transport_execute_tasks(struct se_device *dev, struct se_cmd *);
static void transport_complete_task_attr(struct se_cmd *cmd);
static void transport_handle_queue_full(struct se_cmd *cmd,
struct se_device *dev);
@@ -212,14 +208,13 @@ u32 scsi_get_new_index(scsi_index_t type)
return new_index;
}
-void transport_init_queue_obj(struct se_queue_obj *qobj)
+static void transport_init_queue_obj(struct se_queue_obj *qobj)
{
atomic_set(&qobj->queue_cnt, 0);
INIT_LIST_HEAD(&qobj->qobj_list);
init_waitqueue_head(&qobj->thread_wq);
spin_lock_init(&qobj->cmd_queue_lock);
}
-EXPORT_SYMBOL(transport_init_queue_obj);
void transport_subsystem_check_init(void)
{
@@ -426,18 +421,18 @@ static void transport_all_task_dev_remove_state(struct se_cmd *cmd)
if (task->task_flags & TF_ACTIVE)
continue;
- if (!atomic_read(&task->task_state_active))
- continue;
-
spin_lock_irqsave(&dev->execute_task_lock, flags);
- list_del(&task->t_state_list);
- pr_debug("Removed ITT: 0x%08x dev: %p task[%p]\n",
- cmd->se_tfo->get_task_tag(cmd), dev, task);
- spin_unlock_irqrestore(&dev->execute_task_lock, flags);
+ if (task->t_state_active) {
+ pr_debug("Removed ITT: 0x%08x dev: %p task[%p]\n",
+ cmd->se_tfo->get_task_tag(cmd), dev, task);
- atomic_set(&task->task_state_active, 0);
- atomic_dec(&cmd->t_task_cdbs_ex_left);
+ list_del(&task->t_state_list);
+ atomic_dec(&cmd->t_task_cdbs_ex_left);
+ task->t_state_active = false;
+ }
+ spin_unlock_irqrestore(&dev->execute_task_lock, flags);
}
+
}
/* transport_cmd_check_stop():
@@ -696,12 +691,6 @@ void transport_complete_task(struct se_task *task, int success)
struct se_cmd *cmd = task->task_se_cmd;
struct se_device *dev = cmd->se_dev;
unsigned long flags;
-#if 0
- pr_debug("task: %p CDB: 0x%02x obj_ptr: %p\n", task,
- cmd->t_task_cdb[0], dev);
-#endif
- if (dev)
- atomic_inc(&dev->depth_left);
spin_lock_irqsave(&cmd->t_state_lock, flags);
task->task_flags &= ~TF_ACTIVE;
@@ -714,7 +703,7 @@ void transport_complete_task(struct se_task *task, int success)
if (dev && dev->transport->transport_complete) {
if (dev->transport->transport_complete(task) != 0) {
cmd->se_cmd_flags |= SCF_TRANSPORT_TASK_SENSE;
- task->task_sense = 1;
+ task->task_flags |= TF_HAS_SENSE;
success = 1;
}
}
@@ -743,13 +732,7 @@ void transport_complete_task(struct se_task *task, int success)
}
if (cmd->t_tasks_failed) {
- if (!task->task_error_status) {
- task->task_error_status =
- TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
- cmd->scsi_sense_reason =
- TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
- }
-
+ cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
INIT_WORK(&cmd->work, target_complete_failure_work);
} else {
atomic_set(&cmd->t_transport_complete, 1);
@@ -824,7 +807,7 @@ static void __transport_add_task_to_execute_queue(
head_of_queue = transport_add_task_check_sam_attr(task, task_prev, dev);
atomic_inc(&dev->execute_tasks);
- if (atomic_read(&task->task_state_active))
+ if (task->t_state_active)
return;
/*
* Determine if this task needs to go to HEAD_OF_QUEUE for the
@@ -838,7 +821,7 @@ static void __transport_add_task_to_execute_queue(
else
list_add_tail(&task->t_state_list, &dev->state_task_list);
- atomic_set(&task->task_state_active, 1);
+ task->t_state_active = true;
pr_debug("Added ITT: 0x%08x task[%p] to dev: %p\n",
task->task_se_cmd->se_tfo->get_task_tag(task->task_se_cmd),
@@ -853,29 +836,26 @@ static void transport_add_tasks_to_state_queue(struct se_cmd *cmd)
spin_lock_irqsave(&cmd->t_state_lock, flags);
list_for_each_entry(task, &cmd->t_task_list, t_list) {
- if (atomic_read(&task->task_state_active))
- continue;
-
spin_lock(&dev->execute_task_lock);
- list_add_tail(&task->t_state_list, &dev->state_task_list);
- atomic_set(&task->task_state_active, 1);
-
- pr_debug("Added ITT: 0x%08x task[%p] to dev: %p\n",
- task->task_se_cmd->se_tfo->get_task_tag(
- task->task_se_cmd), task, dev);
-
+ if (!task->t_state_active) {
+ list_add_tail(&task->t_state_list,
+ &dev->state_task_list);
+ task->t_state_active = true;
+
+ pr_debug("Added ITT: 0x%08x task[%p] to dev: %p\n",
+ task->task_se_cmd->se_tfo->get_task_tag(
+ task->task_se_cmd), task, dev);
+ }
spin_unlock(&dev->execute_task_lock);
}
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
}
-static void transport_add_tasks_from_cmd(struct se_cmd *cmd)
+static void __transport_add_tasks_from_cmd(struct se_cmd *cmd)
{
struct se_device *dev = cmd->se_dev;
struct se_task *task, *task_prev = NULL;
- unsigned long flags;
- spin_lock_irqsave(&dev->execute_task_lock, flags);
list_for_each_entry(task, &cmd->t_task_list, t_list) {
if (!list_empty(&task->t_execute_list))
continue;
@@ -886,6 +866,15 @@ static void transport_add_tasks_from_cmd(struct se_cmd *cmd)
__transport_add_task_to_execute_queue(task, task_prev, dev);
task_prev = task;
}
+}
+
+static void transport_add_tasks_from_cmd(struct se_cmd *cmd)
+{
+ unsigned long flags;
+ struct se_device *dev = cmd->se_dev;
+
+ spin_lock_irqsave(&dev->execute_task_lock, flags);
+ __transport_add_tasks_from_cmd(cmd);
spin_unlock_irqrestore(&dev->execute_task_lock, flags);
}
@@ -896,7 +885,7 @@ void __transport_remove_task_from_execute_queue(struct se_task *task,
atomic_dec(&dev->execute_tasks);
}
-void transport_remove_task_from_execute_queue(
+static void transport_remove_task_from_execute_queue(
struct se_task *task,
struct se_device *dev)
{
@@ -983,9 +972,8 @@ void transport_dump_dev_state(
break;
}
- *bl += sprintf(b + *bl, " Execute/Left/Max Queue Depth: %d/%d/%d",
- atomic_read(&dev->execute_tasks), atomic_read(&dev->depth_left),
- dev->queue_depth);
+ *bl += sprintf(b + *bl, " Execute/Max Queue Depth: %d/%d",
+ atomic_read(&dev->execute_tasks), dev->queue_depth);
*bl += sprintf(b + *bl, " SectorSize: %u MaxSectors: %u\n",
dev->se_sub_dev->se_dev_attrib.block_size, dev->se_sub_dev->se_dev_attrib.max_sectors);
*bl += sprintf(b + *bl, " ");
@@ -1340,9 +1328,6 @@ struct se_device *transport_add_device_to_core_hba(
spin_lock_init(&dev->se_port_lock);
spin_lock_init(&dev->se_tmr_lock);
spin_lock_init(&dev->qf_cmd_lock);
-
- dev->queue_depth = dev_limits->queue_depth;
- atomic_set(&dev->depth_left, dev->queue_depth);
atomic_set(&dev->dev_ordered_id, 0);
se_dev_set_default_attribs(dev, dev_limits);
@@ -1654,6 +1639,80 @@ int transport_handle_cdb_direct(
}
EXPORT_SYMBOL(transport_handle_cdb_direct);
+/**
+ * target_submit_cmd - lookup unpacked lun and submit uninitialized se_cmd
+ *
+ * @se_cmd: command descriptor to submit
+ * @se_sess: associated se_sess for endpoint
+ * @cdb: pointer to SCSI CDB
+ * @sense: pointer to SCSI sense buffer
+ * @unpacked_lun: unpacked LUN to reference for struct se_lun
+ * @data_length: fabric expected data transfer length
+ * @task_addr: SAM task attribute
+ * @data_dir: DMA data direction
+ * @flags: flags for command submission from target_sc_flags_tables
+ *
+ * This may only be called from process context, and also currently
+ * assumes internal allocation of fabric payload buffer by target-core.
+ **/
+int target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
+ unsigned char *cdb, unsigned char *sense, u32 unpacked_lun,
+ u32 data_length, int task_attr, int data_dir, int flags)
+{
+ struct se_portal_group *se_tpg;
+ int rc;
+
+ se_tpg = se_sess->se_tpg;
+ BUG_ON(!se_tpg);
+ BUG_ON(se_cmd->se_tfo || se_cmd->se_sess);
+ BUG_ON(in_interrupt());
+ /*
+ * Initialize se_cmd for target operation. From this point
+ * exceptions are handled by sending exception status via
+ * target_core_fabric_ops->queue_status() callback
+ */
+ transport_init_se_cmd(se_cmd, se_tpg->se_tpg_tfo, se_sess,
+ data_length, data_dir, task_attr, sense);
+ /*
+ * Obtain struct se_cmd->cmd_kref reference and add new cmd to
+ * se_sess->sess_cmd_list. A second kref_get here is necessary
+ * for fabrics using TARGET_SCF_ACK_KREF that expect a second
+ * kref_put() to happen during fabric packet acknowledgement.
+ */
+ target_get_sess_cmd(se_sess, se_cmd, (flags & TARGET_SCF_ACK_KREF));
+ /*
+ * Signal bidirectional data payloads to target-core
+ */
+ if (flags & TARGET_SCF_BIDI_OP)
+ se_cmd->se_cmd_flags |= SCF_BIDI;
+ /*
+ * Locate se_lun pointer and attach it to struct se_cmd
+ */
+ if (transport_lookup_cmd_lun(se_cmd, unpacked_lun) < 0)
+ goto out_check_cond;
+ /*
+ * Sanitize CDBs via transport_generic_cmd_sequencer() and
+ * allocate the necessary tasks to complete the received CDB+data
+ */
+ rc = transport_generic_allocate_tasks(se_cmd, cdb);
+ if (rc != 0)
+ goto out_check_cond;
+ /*
+ * Dispatch se_cmd descriptor to se_lun->lun_se_dev backend
+ * for immediate execution of READs, otherwise wait for
+ * transport_generic_handle_data() to be called for WRITEs
+ * when fabric has filled the incoming buffer.
+ */
+ transport_handle_cdb_direct(se_cmd);
+ return 0;
+
+out_check_cond:
+ transport_send_check_condition_and_sense(se_cmd,
+ se_cmd->scsi_sense_reason, 0);
+ return 0;
+}
+EXPORT_SYMBOL(target_submit_cmd);
+
/*
* Used by fabric module frontends defining a TFO->new_cmd_map() caller
* to queue up a newly setup se_cmd w/ TRANSPORT_NEW_CMD_MAP in order to
@@ -1920,18 +1979,6 @@ static void transport_set_supported_SAM_opcode(struct se_cmd *se_cmd)
spin_unlock_irqrestore(&se_cmd->t_state_lock, flags);
}
-static inline int transport_tcq_window_closed(struct se_device *dev)
-{
- if (dev->dev_tcq_window_closed++ <
- PYX_TRANSPORT_WINDOW_CLOSED_THRESHOLD) {
- msleep(PYX_TRANSPORT_WINDOW_CLOSED_WAIT_SHORT);
- } else
- msleep(PYX_TRANSPORT_WINDOW_CLOSED_WAIT_LONG);
-
- wake_up_interruptible(&dev->dev_queue_obj.thread_wq);
- return 0;
-}
-
/*
* Called from Fabric Module context from transport_execute_tasks()
*
@@ -2014,13 +2061,7 @@ static inline int transport_execute_task_attr(struct se_cmd *cmd)
static int transport_execute_tasks(struct se_cmd *cmd)
{
int add_tasks;
-
- if (se_dev_check_online(cmd->se_dev) != 0) {
- cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
- transport_generic_request_failure(cmd);
- return 0;
- }
-
+ struct se_device *se_dev = cmd->se_dev;
/*
* Call transport_cmd_check_stop() to see if a fabric exception
* has occurred that prevents execution.
@@ -2034,19 +2075,16 @@ static int transport_execute_tasks(struct se_cmd *cmd)
if (!add_tasks)
goto execute_tasks;
/*
- * This calls transport_add_tasks_from_cmd() to handle
- * HEAD_OF_QUEUE ordering for SAM Task Attribute emulation
- * (if enabled) in __transport_add_task_to_execute_queue() and
- * transport_add_task_check_sam_attr().
+ * __transport_execute_tasks() -> __transport_add_tasks_from_cmd()
+ * adds associated se_tasks while holding dev->execute_task_lock
+ * before I/O dispath to avoid a double spinlock access.
*/
- transport_add_tasks_from_cmd(cmd);
+ __transport_execute_tasks(se_dev, cmd);
+ return 0;
}
- /*
- * Kick the execution queue for the cmd associated struct se_device
- * storage object.
- */
+
execute_tasks:
- __transport_execute_tasks(cmd->se_dev);
+ __transport_execute_tasks(se_dev, NULL);
return 0;
}
@@ -2056,24 +2094,18 @@ execute_tasks:
*
* Called from transport_processing_thread()
*/
-static int __transport_execute_tasks(struct se_device *dev)
+static int __transport_execute_tasks(struct se_device *dev, struct se_cmd *new_cmd)
{
int error;
struct se_cmd *cmd = NULL;
struct se_task *task = NULL;
unsigned long flags;
- /*
- * Check if there is enough room in the device and HBA queue to send
- * struct se_tasks to the selected transport.
- */
check_depth:
- if (!atomic_read(&dev->depth_left))
- return transport_tcq_window_closed(dev);
-
- dev->dev_tcq_window_closed = 0;
-
spin_lock_irq(&dev->execute_task_lock);
+ if (new_cmd != NULL)
+ __transport_add_tasks_from_cmd(new_cmd);
+
if (list_empty(&dev->execute_task_list)) {
spin_unlock_irq(&dev->execute_task_lock);
return 0;
@@ -2083,10 +2115,7 @@ check_depth:
__transport_remove_task_from_execute_queue(task, dev);
spin_unlock_irq(&dev->execute_task_lock);
- atomic_dec(&dev->depth_left);
-
cmd = task->task_se_cmd;
-
spin_lock_irqsave(&cmd->t_state_lock, flags);
task->task_flags |= (TF_ACTIVE | TF_SENT);
atomic_inc(&cmd->t_task_cdbs_sent);
@@ -2107,10 +2136,10 @@ check_depth:
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
atomic_set(&cmd->t_transport_sent, 0);
transport_stop_tasks_for_cmd(cmd);
- atomic_inc(&dev->depth_left);
transport_generic_request_failure(cmd);
}
+ new_cmd = NULL;
goto check_depth;
return 0;
@@ -2351,7 +2380,7 @@ static int transport_get_sense_data(struct se_cmd *cmd)
list_for_each_entry_safe(task, task_tmp,
&cmd->t_task_list, t_list) {
- if (!task->task_sense)
+ if (!(task->task_flags & TF_HAS_SENSE))
continue;
if (!dev->transport->get_sense_buffer) {
@@ -3346,6 +3375,32 @@ static inline void transport_free_pages(struct se_cmd *cmd)
}
/**
+ * transport_release_cmd - free a command
+ * @cmd: command to free
+ *
+ * This routine unconditionally frees a command, and reference counting
+ * or list removal must be done in the caller.
+ */
+static void transport_release_cmd(struct se_cmd *cmd)
+{
+ BUG_ON(!cmd->se_tfo);
+
+ if (cmd->se_tmr_req)
+ core_tmr_release_req(cmd->se_tmr_req);
+ if (cmd->t_task_cdb != cmd->__t_task_cdb)
+ kfree(cmd->t_task_cdb);
+ /*
+ * If this cmd has been setup with target_get_sess_cmd(), drop
+ * the kref and call ->release_cmd() in kref callback.
+ */
+ if (cmd->check_release != 0) {
+ target_put_sess_cmd(cmd->se_sess, cmd);
+ return;
+ }
+ cmd->se_tfo->release_cmd(cmd);
+}
+
+/**
* transport_put_cmd - release a reference to a command
* @cmd: command to release
*
@@ -3870,33 +3925,6 @@ queue_full:
return 0;
}
-/**
- * transport_release_cmd - free a command
- * @cmd: command to free
- *
- * This routine unconditionally frees a command, and reference counting
- * or list removal must be done in the caller.
- */
-void transport_release_cmd(struct se_cmd *cmd)
-{
- BUG_ON(!cmd->se_tfo);
-
- if (cmd->se_tmr_req)
- core_tmr_release_req(cmd->se_tmr_req);
- if (cmd->t_task_cdb != cmd->__t_task_cdb)
- kfree(cmd->t_task_cdb);
- /*
- * Check if target_wait_for_sess_cmds() is expecting to
- * release se_cmd directly here..
- */
- if (cmd->check_release != 0 && cmd->se_tfo->check_release_cmd)
- if (cmd->se_tfo->check_release_cmd(cmd) != 0)
- return;
-
- cmd->se_tfo->release_cmd(cmd);
-}
-EXPORT_SYMBOL(transport_release_cmd);
-
void transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks)
{
if (!(cmd->se_cmd_flags & SCF_SE_LUN_CMD)) {
@@ -3923,11 +3951,22 @@ EXPORT_SYMBOL(transport_generic_free_cmd);
/* target_get_sess_cmd - Add command to active ->sess_cmd_list
* @se_sess: session to reference
* @se_cmd: command descriptor to add
+ * @ack_kref: Signal that fabric will perform an ack target_put_sess_cmd()
*/
-void target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd)
+void target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd,
+ bool ack_kref)
{
unsigned long flags;
+ kref_init(&se_cmd->cmd_kref);
+ /*
+ * Add a second kref if the fabric caller is expecting to handle
+ * fabric acknowledgement that requires two target_put_sess_cmd()
+ * invocations before se_cmd descriptor release.
+ */
+ if (ack_kref == true)
+ kref_get(&se_cmd->cmd_kref);
+
spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
list_add_tail(&se_cmd->se_cmd_list, &se_sess->sess_cmd_list);
se_cmd->check_release = 1;
@@ -3935,30 +3974,36 @@ void target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd)
}
EXPORT_SYMBOL(target_get_sess_cmd);
-/* target_put_sess_cmd - Check for active I/O shutdown or list delete
- * @se_sess: session to reference
- * @se_cmd: command descriptor to drop
- */
-int target_put_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd)
+static void target_release_cmd_kref(struct kref *kref)
{
+ struct se_cmd *se_cmd = container_of(kref, struct se_cmd, cmd_kref);
+ struct se_session *se_sess = se_cmd->se_sess;
unsigned long flags;
spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
if (list_empty(&se_cmd->se_cmd_list)) {
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
WARN_ON(1);
- return 0;
+ return;
}
-
if (se_sess->sess_tearing_down && se_cmd->cmd_wait_set) {
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
complete(&se_cmd->cmd_wait_comp);
- return 1;
+ return;
}
list_del(&se_cmd->se_cmd_list);
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
- return 0;
+ se_cmd->se_tfo->release_cmd(se_cmd);
+}
+
+/* target_put_sess_cmd - Check for active I/O shutdown via kref_put
+ * @se_sess: session to reference
+ * @se_cmd: command descriptor to drop
+ */
+int target_put_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd)
+{
+ return kref_put(&se_cmd->cmd_kref, target_release_cmd_kref);
}
EXPORT_SYMBOL(target_put_sess_cmd);
@@ -4174,7 +4219,7 @@ check_cond:
static int transport_clear_lun_thread(void *p)
{
- struct se_lun *lun = (struct se_lun *)p;
+ struct se_lun *lun = p;
__transport_clear_lun_from_sessions(lun);
complete(&lun->lun_shutdown_comp);
@@ -4353,6 +4398,7 @@ int transport_send_check_condition_and_sense(
case TCM_NON_EXISTENT_LUN:
/* CURRENT ERROR */
buffer[offset] = 0x70;
+ buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
/* ILLEGAL REQUEST */
buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
/* LOGICAL UNIT NOT SUPPORTED */
@@ -4362,6 +4408,7 @@ int transport_send_check_condition_and_sense(
case TCM_SECTOR_COUNT_TOO_MANY:
/* CURRENT ERROR */
buffer[offset] = 0x70;
+ buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
/* ILLEGAL REQUEST */
buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
/* INVALID COMMAND OPERATION CODE */
@@ -4370,6 +4417,7 @@ int transport_send_check_condition_and_sense(
case TCM_UNKNOWN_MODE_PAGE:
/* CURRENT ERROR */
buffer[offset] = 0x70;
+ buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
/* ILLEGAL REQUEST */
buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
/* INVALID FIELD IN CDB */
@@ -4378,6 +4426,7 @@ int transport_send_check_condition_and_sense(
case TCM_CHECK_CONDITION_ABORT_CMD:
/* CURRENT ERROR */
buffer[offset] = 0x70;
+ buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
/* ABORTED COMMAND */
buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
/* BUS DEVICE RESET FUNCTION OCCURRED */
@@ -4387,6 +4436,7 @@ int transport_send_check_condition_and_sense(
case TCM_INCORRECT_AMOUNT_OF_DATA:
/* CURRENT ERROR */
buffer[offset] = 0x70;
+ buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
/* ABORTED COMMAND */
buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
/* WRITE ERROR */
@@ -4397,6 +4447,7 @@ int transport_send_check_condition_and_sense(
case TCM_INVALID_CDB_FIELD:
/* CURRENT ERROR */
buffer[offset] = 0x70;
+ buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
/* ABORTED COMMAND */
buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
/* INVALID FIELD IN CDB */
@@ -4405,6 +4456,7 @@ int transport_send_check_condition_and_sense(
case TCM_INVALID_PARAMETER_LIST:
/* CURRENT ERROR */
buffer[offset] = 0x70;
+ buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
/* ABORTED COMMAND */
buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
/* INVALID FIELD IN PARAMETER LIST */
@@ -4413,6 +4465,7 @@ int transport_send_check_condition_and_sense(
case TCM_UNEXPECTED_UNSOLICITED_DATA:
/* CURRENT ERROR */
buffer[offset] = 0x70;
+ buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
/* ABORTED COMMAND */
buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
/* WRITE ERROR */
@@ -4423,6 +4476,7 @@ int transport_send_check_condition_and_sense(
case TCM_SERVICE_CRC_ERROR:
/* CURRENT ERROR */
buffer[offset] = 0x70;
+ buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
/* ABORTED COMMAND */
buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
/* PROTOCOL SERVICE CRC ERROR */
@@ -4433,6 +4487,7 @@ int transport_send_check_condition_and_sense(
case TCM_SNACK_REJECTED:
/* CURRENT ERROR */
buffer[offset] = 0x70;
+ buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
/* ABORTED COMMAND */
buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
/* READ ERROR */
@@ -4443,6 +4498,7 @@ int transport_send_check_condition_and_sense(
case TCM_WRITE_PROTECTED:
/* CURRENT ERROR */
buffer[offset] = 0x70;
+ buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
/* DATA PROTECT */
buffer[offset+SPC_SENSE_KEY_OFFSET] = DATA_PROTECT;
/* WRITE PROTECTED */
@@ -4451,6 +4507,7 @@ int transport_send_check_condition_and_sense(
case TCM_CHECK_CONDITION_UNIT_ATTENTION:
/* CURRENT ERROR */
buffer[offset] = 0x70;
+ buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
/* UNIT ATTENTION */
buffer[offset+SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION;
core_scsi3_ua_for_check_condition(cmd, &asc, &ascq);
@@ -4460,6 +4517,7 @@ int transport_send_check_condition_and_sense(
case TCM_CHECK_CONDITION_NOT_READY:
/* CURRENT ERROR */
buffer[offset] = 0x70;
+ buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
/* Not Ready */
buffer[offset+SPC_SENSE_KEY_OFFSET] = NOT_READY;
transport_get_sense_codes(cmd, &asc, &ascq);
@@ -4470,6 +4528,7 @@ int transport_send_check_condition_and_sense(
default:
/* CURRENT ERROR */
buffer[offset] = 0x70;
+ buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
/* ILLEGAL REQUEST */
buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
/* LOGICAL UNIT COMMUNICATION FAILURE */
@@ -4545,11 +4604,7 @@ void transport_send_task_abort(struct se_cmd *cmd)
cmd->se_tfo->queue_status(cmd);
}
-/* transport_generic_do_tmr():
- *
- *
- */
-int transport_generic_do_tmr(struct se_cmd *cmd)
+static int transport_generic_do_tmr(struct se_cmd *cmd)
{
struct se_device *dev = cmd->se_dev;
struct se_tmr_req *tmr = cmd->se_tmr_req;
@@ -4597,7 +4652,7 @@ static int transport_processing_thread(void *param)
{
int ret;
struct se_cmd *cmd;
- struct se_device *dev = (struct se_device *) param;
+ struct se_device *dev = param;
while (!kthread_should_stop()) {
ret = wait_event_interruptible(dev->dev_queue_obj.thread_wq,
@@ -4607,8 +4662,6 @@ static int transport_processing_thread(void *param)
goto out;
get_cmd:
- __transport_execute_tasks(dev);
-
cmd = transport_get_cmd_from_queue(&dev->dev_queue_obj);
if (!cmd)
continue;
diff --git a/drivers/target/target_core_ua.c b/drivers/target/target_core_ua.c
index 50a480db7a66..3e12f6bcfa10 100644
--- a/drivers/target/target_core_ua.c
+++ b/drivers/target/target_core_ua.c
@@ -30,13 +30,11 @@
#include <scsi/scsi_cmnd.h>
#include <target/target_core_base.h>
-#include <target/target_core_device.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_fabric.h>
#include <target/target_core_configfs.h>
+#include "target_core_internal.h"
#include "target_core_alua.h"
-#include "target_core_hba.h"
#include "target_core_pr.h"
#include "target_core_ua.h"
diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c
index 71fc9cea5dc9..addc18f727ea 100644
--- a/drivers/target/tcm_fc/tfc_cmd.c
+++ b/drivers/target/tcm_fc/tfc_cmd.c
@@ -39,12 +39,8 @@
#include <scsi/fc_encode.h>
#include <target/target_core_base.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
-#include <target/target_core_device.h>
-#include <target/target_core_tpg.h>
+#include <target/target_core_fabric.h>
#include <target/target_core_configfs.h>
-#include <target/target_core_tmr.h>
#include <target/configfs_macros.h>
#include "tcm_fc.h"
@@ -367,6 +363,11 @@ static void ft_send_tm(struct ft_cmd *cmd)
struct ft_sess *sess;
u8 tm_func;
+ transport_init_se_cmd(&cmd->se_cmd, &ft_configfs->tf_ops,
+ cmd->sess->se_sess, 0, DMA_NONE, 0,
+ &cmd->ft_sense_buffer[0]);
+ target_get_sess_cmd(cmd->sess->se_sess, &cmd->se_cmd, false);
+
fcp = fc_frame_payload_get(cmd->req_frame, sizeof(*fcp));
switch (fcp->fc_tm_flags) {
@@ -420,7 +421,6 @@ static void ft_send_tm(struct ft_cmd *cmd)
sess = cmd->sess;
transport_send_check_condition_and_sense(&cmd->se_cmd,
cmd->se_cmd.scsi_sense_reason, 0);
- transport_generic_free_cmd(&cmd->se_cmd, 0);
ft_sess_put(sess);
return;
}
@@ -536,7 +536,6 @@ static void ft_send_work(struct work_struct *work)
{
struct ft_cmd *cmd = container_of(work, struct ft_cmd, work);
struct fc_frame_header *fh = fc_frame_header_get(cmd->req_frame);
- struct se_cmd *se_cmd;
struct fcp_cmnd *fcp;
int data_dir = 0;
u32 data_len;
@@ -591,15 +590,6 @@ static void ft_send_work(struct work_struct *work)
data_len = ntohl(fcp->fc_dl);
cmd->cdb = fcp->fc_cdb;
}
-
- se_cmd = &cmd->se_cmd;
- /*
- * Initialize struct se_cmd descriptor from target_core_mod
- * infrastructure
- */
- transport_init_se_cmd(se_cmd, &ft_configfs->tf_ops, cmd->sess->se_sess,
- data_len, data_dir, task_attr,
- &cmd->ft_sense_buffer[0]);
/*
* Check for FCP task management flags
*/
@@ -607,39 +597,20 @@ static void ft_send_work(struct work_struct *work)
ft_send_tm(cmd);
return;
}
-
fc_seq_exch(cmd->seq)->lp->tt.seq_set_resp(cmd->seq, ft_recv_seq, cmd);
-
cmd->lun = scsilun_to_int((struct scsi_lun *)fcp->fc_lun);
- ret = transport_lookup_cmd_lun(&cmd->se_cmd, cmd->lun);
+ /*
+ * Use a single se_cmd->cmd_kref as we expect to release se_cmd
+ * directly from ft_check_stop_free callback in response path.
+ */
+ ret = target_submit_cmd(&cmd->se_cmd, cmd->sess->se_sess, cmd->cdb,
+ &cmd->ft_sense_buffer[0], cmd->lun, data_len,
+ task_attr, data_dir, 0);
+ pr_debug("r_ctl %x alloc target_submit_cmd %d\n", fh->fh_r_ctl, ret);
if (ret < 0) {
ft_dump_cmd(cmd, __func__);
- transport_send_check_condition_and_sense(&cmd->se_cmd,
- cmd->se_cmd.scsi_sense_reason, 0);
- return;
- }
-
- ret = transport_generic_allocate_tasks(se_cmd, cmd->cdb);
-
- pr_debug("r_ctl %x alloc task ret %d\n", fh->fh_r_ctl, ret);
- ft_dump_cmd(cmd, __func__);
-
- if (ret == -ENOMEM) {
- transport_send_check_condition_and_sense(se_cmd,
- TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE, 0);
- transport_generic_free_cmd(se_cmd, 0);
- return;
- }
- if (ret == -EINVAL) {
- if (se_cmd->se_cmd_flags & SCF_SCSI_RESERVATION_CONFLICT)
- ft_queue_status(se_cmd);
- else
- transport_send_check_condition_and_sense(se_cmd,
- se_cmd->scsi_sense_reason, 0);
- transport_generic_free_cmd(se_cmd, 0);
return;
}
- transport_handle_cdb_direct(se_cmd);
return;
err:
diff --git a/drivers/target/tcm_fc/tfc_conf.c b/drivers/target/tcm_fc/tfc_conf.c
index 9402b7387cac..73852fbc857b 100644
--- a/drivers/target/tcm_fc/tfc_conf.c
+++ b/drivers/target/tcm_fc/tfc_conf.c
@@ -41,12 +41,8 @@
#include <scsi/libfc.h>
#include <target/target_core_base.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
+#include <target/target_core_fabric.h>
#include <target/target_core_fabric_configfs.h>
-#include <target/target_core_fabric_lib.h>
-#include <target/target_core_device.h>
-#include <target/target_core_tpg.h>
#include <target/target_core_configfs.h>
#include <target/configfs_macros.h>
diff --git a/drivers/target/tcm_fc/tfc_io.c b/drivers/target/tcm_fc/tfc_io.c
index 1369b1cb103d..d8cabc21036d 100644
--- a/drivers/target/tcm_fc/tfc_io.c
+++ b/drivers/target/tcm_fc/tfc_io.c
@@ -48,10 +48,7 @@
#include <scsi/fc_encode.h>
#include <target/target_core_base.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
-#include <target/target_core_device.h>
-#include <target/target_core_tpg.h>
+#include <target/target_core_fabric.h>
#include <target/target_core_configfs.h>
#include <target/configfs_macros.h>
diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c
index 326921385aff..4c0507cf808c 100644
--- a/drivers/target/tcm_fc/tfc_sess.c
+++ b/drivers/target/tcm_fc/tfc_sess.c
@@ -40,10 +40,7 @@
#include <scsi/libfc.h>
#include <target/target_core_base.h>
-#include <target/target_core_transport.h>
-#include <target/target_core_fabric_ops.h>
-#include <target/target_core_device.h>
-#include <target/target_core_tpg.h>
+#include <target/target_core_fabric.h>
#include <target/target_core_configfs.h>
#include <target/configfs_macros.h>
diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c
index 6a1241c7f841..de88aa5566e5 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 f32a2ea70100..aca2386c5ef1 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 07e0494c6830..f5b01f2ce525 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 6958594f2fc0..9ae024025ff3 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 000000000000..e4f60e2b87f3
--- /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 de0f613ed6f5..17ae65762d1a 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 9e62349b3d9f..75085795528e 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -1339,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;
@@ -1454,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 */
diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c
index e67fb20490d2..ff8017f87914 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 0f6b796c95c5..a7efe538df00 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/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
index b42092e1f164..98dd9e49b684 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 00f171a7a8a0..01ea5d7421d4 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 3af5e2dd1d82..8df4b76465ac 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 79d339e2e700..a0613d8f9be7 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 1382c90d0834..8ca9f994a280 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 e9a2c5c44454..c16ff55a74e8 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 0cd764d59351..a28f6ffcd0f3 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 e0f30fc70e45..47766f0e7caa 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 4c81d540bc26..7322d293213e 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 cf1f36454d08..cdedd1336745 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 7db5bbe6251b..576cd8578b45 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 dd2313cce1d3..a3fcaae4bc2a 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 ed1b816e58d8..ad9e5b2df642 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 20697cc132d1..31d34832907e 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 4c0c9734251d..91413cac97be 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 b4192c964d0d..936af8359fb2 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 afb6743cf094..f1424f9bc363 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 e311a511529b..a007a9fe0f87 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 32793ce3d9e9..9c2cc4633894 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 40d886adff53..4ea63b2cac42 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 5f5a63241436..34b9edd86651 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 6f62de5c6e35..015c7c62ed49 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 533d12cca371..16dd6a6abf00 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 c8ae199cfbb8..6b5eb1017e2c 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 2dbe600fbc11..a4a3c7cd4a11 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 2453a39b4794..4fd0dc835ae5 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 53be7aef6308..66bc376005d2 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 f6ff7923048b..56cf0243979e 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 a163632877af..97cb45916c43 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 07ccea9ada40..74fe6e62e0f7 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 b51fcd80d244..72339bd6fcab 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 b43d07df4c44..123bf9155339 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 18e875b92e00..69328dcfd91a 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 f9f29b289f2f..29ffeb6279c7 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 0e77511060c0..5e53cc59e652 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 adfe660ed008..fba1147ed916 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 98bf83349838..6bc3802a581a 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 07680d6b792b..3bdeafa29c24 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 6d26a77d0f2a..b23bebd721a1 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 504b5585ea45..aced6817bf95 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 c290df97108e..01b6404df395 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 e21ce9ddfc63..5d4b099dcf8b 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 bf12565f8e87..21343378c322 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 abd2ee2b2f99..0497575e4799 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 e44d375edaad..65bf06aa591a 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 36f5cbe90485..06053a920dd8 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 5170799d6e94..6f9356f3f99e 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 0c537da0d3cd..84a396e83671 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 64d0ffd4440b..3077a4436976 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 bc8dc203e818..4cc36c761801 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 a40615674a68..7c62a7048302 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 19373cb7c5bf..fc064e1442ca 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 a975bb80303f..27fa9c8a77b0 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 19d112f51b97..4554ee49e635 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 55cfd6265b98..03b5e249e95e 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 1f00f243c26c..b28f1db0195f 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 45a8c55881d3..8b8d58a2ac12 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 691f57a9d712..262ded9e076b 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 c96b6b6509fb..420d9857394a 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 2161d1c3c089..e287fd32682c 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 329295615d06..3d8cda57ce7a 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 aa9367f5b421..1d5deee3be52 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 a36e2313eed0..d074b3740dcb 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 f2485429172f..fdae0a4407cb 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 180ea6c7911c..d7f5eee18f00 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 87362e48796e..7697858d8858 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 c70cc012d03f..50651cf4fc61 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 4af21f46096e..8468eb769a29 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 ce6c1a65a544..611b206591cb 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 d555ca9567b8..c88657dd31c8 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 1c11959a7d58..210e4b10dc11 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 11af903cb09f..7e0acf5c8e38 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/video/Kconfig b/drivers/video/Kconfig
index d83e967e4e15..6ca0c407c144 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 9b9d8fff7732..142606814d98 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 5ea6596dd824..f23cae094f1b 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 63409c122ae8..0d7b20d4285d 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 44bdce4242ad..622f12b62a47 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 150684882ef7..ce1506b75adf 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 649cb35de4ed..de9da6774fd9 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 72005598040f..04e4479d5afd 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/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c
index 66bc74d9ce2a..378276c9d3cf 100644
--- a/drivers/video/backlight/adp8860_bl.c
+++ b/drivers/video/backlight/adp8860_bl.c
@@ -146,7 +146,7 @@ static int adp8860_set_bits(struct i2c_client *client, int reg, uint8_t bit_mask
ret = adp8860_read(client, reg, &reg_val);
- if (!ret && ((reg_val & bit_mask) == 0)) {
+ if (!ret && ((reg_val & bit_mask) != bit_mask)) {
reg_val |= bit_mask;
ret = adp8860_write(client, reg, reg_val);
}
diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c
index 6c68a6899e87..6735059376d6 100644
--- a/drivers/video/backlight/adp8870_bl.c
+++ b/drivers/video/backlight/adp8870_bl.c
@@ -160,7 +160,7 @@ static int adp8870_set_bits(struct i2c_client *client, int reg, uint8_t bit_mask
ret = adp8870_read(client, reg, &reg_val);
- if (!ret && ((reg_val & bit_mask) == 0)) {
+ if (!ret && ((reg_val & bit_mask) != bit_mask)) {
reg_val |= bit_mask;
ret = adp8870_write(client, reg, reg_val);
}
diff --git a/drivers/video/backlight/l4f00242t03.c b/drivers/video/backlight/l4f00242t03.c
index 4f5d1c4cb6ab..27d1d7a29c77 100644
--- a/drivers/video/backlight/l4f00242t03.c
+++ b/drivers/video/backlight/l4f00242t03.c
@@ -190,6 +190,7 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi)
priv->io_reg = regulator_get(&spi->dev, "vdd");
if (IS_ERR(priv->io_reg)) {
+ ret = PTR_ERR(priv->io_reg);
dev_err(&spi->dev, "%s: Unable to get the IO regulator\n",
__func__);
goto err3;
@@ -197,6 +198,7 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi)
priv->core_reg = regulator_get(&spi->dev, "vcore");
if (IS_ERR(priv->core_reg)) {
+ ret = PTR_ERR(priv->core_reg);
dev_err(&spi->dev, "%s: Unable to get the core regulator\n",
__func__);
goto err4;
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index 6df7c54db0a3..738c8ce7d132 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 93317b5b8740..a122d9287d16 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 7b2c40abae15..0c189b32a4c5 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 f99af931d4f8..000000000000
--- 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 c0ea832bf171..000000000000
--- 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 0c647d7af0ee..000000000000
--- 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 ad936295d8f4..ac9141b85356 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 a16beeb5f548..acf292bfba02 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 f37e02538203..da066c210923 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 4394389caf68..c645f9282650 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 318f6fb895b2..b83f36190cae 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 5ba399991050..c6afa33a4532 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 ea7a8ccc830c..080c35b34bbb 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 44bf8d4a216b..401a56e250bd 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 d7112c39614b..02796a4317a9 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 6ce34160da78..55bf6196b7a0 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 e3406ab31305..727a5149d818 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 eb3c5eea1a0f..4a89f889852d 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 feea7b1dc386..fb3f67391105 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 d1fbbd888cf4..e10f551ade21 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/omap/lcd_ams_delta.c b/drivers/video/omap/lcd_ams_delta.c
index 6978ae4ef83a..0fdd6f6873bf 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 622ad839fd9d..49bdeca81e50 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 4802419da83b..20f477851d54 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 3271f1643b26..b38b1dd15ce3 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 12cc52a70f96..7e8bd8e08a98 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 eb381db7fe51..8d546dd55e81 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 6f8d13c41202..5914220dfa9c 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 4cb301750d02..88c31eb0cd6c 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 b51b332e5a2b..aaf3c8ba1243 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 2334e56536bc..3b7d8aa1cf34 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 25d8e5103193..b291bfaac80e 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 8d8e1fe1901c..74d29b552901 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 dbd59b8e5b36..51a87e149e24 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 519c47d2057f..28b9a6d61b0f 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 150e8bae35a1..dc9408dc93d1 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 2ba9d0ca187c..0eb31caddca8 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 80c3f6ab1a94..00c5c615585f 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 2462b9ec6662..e6649aa89591 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 bd34ac5b2026..5c450b0f94d0 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 000000000000..052dc874cd3d
--- /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 86ec12e16c7c..8613f86fb56d 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 5c81533eacaa..a5ec7f37c185 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 c06efc38983e..5836bd1650f9 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 000000000000..069bccbb3f12
--- /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 976ac23dcd0c..395d658a94fc 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 5abf8e7e7456..d4d676c82c12 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 6308fc59fc9e..32ff69fb3333 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 b402699168a5..afcb59301c37 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 6a6c05dd45ce..cd833bbaac3d 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 c56378c555b0..b4c270edb915 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 6e63845cc7d7..d1858e71c64e 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 ab8e40e48759..6e821810deec 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 1130c608a561..814bb9500dca 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 40305ad7841e..8266ca0d666b 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 2c3443dabb14..7503f7f619a7 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 e1a6ce518af6..9af81f18f163 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 204095632d27..a442998980f1 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 7533458ba4d2..b3e9f9091581 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 df7bcce5b107..16ba6196f330 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 70aa47de7146..ce158311ff59 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 1694d5148f32..e8d8cc76a435 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 fdf0edeccf4e..c0bdc9b54ecf 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 dc7bfa91e57a..df31a24a5026 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 6632ee5ecb7e..055e527a8e45 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 b2252fea2858..6d30428e9cf9 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 50e00395240f..c5c741452cac 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 18ead6f0184d..8384b941f6ba 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 1ed8b366618d..1d71c08a818f 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 d8ab7be4fd6b..2f58cf9c813b 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 0753b1cfcb8b..0c63b69b6340 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 ee4c0df217f7..77f34c614c86 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 946a949f4c7d..2c80246b18b8 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 37d764ad56b0..3c1de981a18c 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 45e47d847163..83b16e237a0e 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 72ee96bc6b3e..05151b82f40f 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 facffc254976..aac5b369d73c 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 4d63490209cd..f45d83ecfd21 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 a78254cf8e83..3690effbedcc 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 3c22994ea31a..ccbfef5e828f 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 2301c275d63a..111fb32e8769 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 a99b994c9b6b..e026724a3a56 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 1f868d0187a2..a19773149bd7 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 7f8472cc993b..e7f69ef572dc 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 bf2f78065cf9..501a922aa9dc 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 777c21dd7a6b..2a5fe6ede845 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 2375e5bbf572..90a2e30272ad 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 96e34a569169..c8703bd61b74 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 45832b7ef7d2..55be3865015b 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 fcb6cd90f64d..18084525402a 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/watchdog/f71808e_wdt.c b/drivers/watchdog/f71808e_wdt.c
index d4d8d1fdccc4..e45ca2b4bfbe 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 eed5436ffb51..20feb4d3d791 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 ba6eda4b5143..0edb91c0de6b 100644
--- a/drivers/xen/biomerge.c
+++ b/drivers/xen/biomerge.c
@@ -1,5 +1,6 @@
#include <linux/bio.h>
#include <linux/io.h>
+#include <linux/export.h>
#include <xen/page.h>
bool xen_biovec_phys_mergeable(const struct bio_vec *vec1,
@@ -11,3 +12,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 3832e303c33a..596e6a7b17d6 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 52fed16d8701..30d7be026c18 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 8e1c44d8ab46..d5dcf8d5d3d9 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"\